<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Jboot | 目录</title>
    <meta name="description" content="一个开源的分布式、商业级微服务框架">
    
    
    <link rel="preload" href="/assets/css/5.styles.1d6de0dd.css" as="style"><link rel="preload" href="/assets/js/app.7f52c12a.js" as="script"><link rel="preload" href="/assets/js/2.676f353b.js" as="script"><link rel="prefetch" href="/assets/js/0.06af09ca.js"><link rel="prefetch" href="/assets/js/1.f8730824.js"><link rel="prefetch" href="/assets/js/3.aba6aeba.js"><link rel="prefetch" href="/assets/js/4.f18705ea.js">
    <link rel="stylesheet" href="/assets/css/5.styles.1d6de0dd.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div><a href="/" class="home-link router-link-active"><!----><span class="site-name">
      Jboot
    </span></a><div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""><!----></div><nav class="nav-links can-hide"><div class="nav-item"><a href="/" class="nav-link">首页</a></div><div class="nav-item"><a href="/started/" class="nav-link">开始</a></div><div class="nav-item"><a href="/docs/" class="nav-link">文档</a></div><div class="nav-item"><a href="/benchmark/" class="nav-link">性能</a></div><div class="nav-item"><a href="https://www.oschina.net/question/tag/jboot" target="_blank" rel="noopener noreferrer" class="nav-link">提问</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">源码下载</span><span class="arrow right"></span></a><ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----><a href="https://gitee.com/fuhai/jboot" target="_blank" rel="noopener noreferrer" class="nav-link">Gitee</a></li><li class="dropdown-item"><!----><a href="https://github.com/yangfuhai/jboot" target="_blank" rel="noopener noreferrer" class="nav-link">Github</a></li></ul></div></div><!----></nav></div></header><div class="sidebar-mask"></div><div class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/" class="nav-link">首页</a></div><div class="nav-item"><a href="/started/" class="nav-link">开始</a></div><div class="nav-item"><a href="/docs/" class="nav-link">文档</a></div><div class="nav-item"><a href="/benchmark/" class="nav-link">性能</a></div><div class="nav-item"><a href="https://www.oschina.net/question/tag/jboot" target="_blank" rel="noopener noreferrer" class="nav-link">提问</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">源码下载</span><span class="arrow right"></span></a><ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----><a href="https://gitee.com/fuhai/jboot" target="_blank" rel="noopener noreferrer" class="nav-link">Gitee</a></li><li class="dropdown-item"><!----><a href="https://github.com/yangfuhai/jboot" target="_blank" rel="noopener noreferrer" class="nav-link">Github</a></li></ul></div></div><!----></nav><ul class="sidebar-links"><li><div class="sidebar-group first"><p class="sidebar-heading open"><span>目录</span><!----></p><ul class="sidebar-group-items"><li><a href="/doc.html#mvc的概念" class="sidebar-link">MVC的概念</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#controller" class="sidebar-link">Controller</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/doc.html#jbootcontroller" class="sidebar-link">JbootController</a></li><li class="sidebar-sub-header"><a href="/doc.html#rquestmapping" class="sidebar-link">@RquestMapping</a></li><li class="sidebar-sub-header"><a href="/doc.html#action" class="sidebar-link">Action</a></li><li class="sidebar-sub-header"><a href="/doc.html#getpara-系列方法" class="sidebar-link">getPara 系列方法</a></li><li class="sidebar-sub-header"><a href="/doc.html#getbean-与-getmodel-方法" class="sidebar-link">getBean 与 getModel 方法</a></li><li class="sidebar-sub-header"><a href="/doc.html#render" class="sidebar-link">render</a></li><li class="sidebar-sub-header"><a href="/doc.html#session-与-分布式session" class="sidebar-link">session 与 分布式session</a></li><li class="sidebar-sub-header"><a href="/doc.html#限流和流量控制" class="sidebar-link">限流和流量控制</a></li></ul></li><li><a href="/doc.html#websocket" class="sidebar-link">websocket</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#shiro简介" class="sidebar-link">shiro简介</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#shiro的配置" class="sidebar-link">shiro的配置</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#shiro的使用" class="sidebar-link">shiro的使用</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/doc.html#_12个模板指令（用在html上）" class="sidebar-link">12个模板指令（用在html上）</a></li><li class="sidebar-sub-header"><a href="/doc.html#_5个requires注解功能（用在controller上）" class="sidebar-link">5个Requires注解功能（用在Controller上）</a></li></ul></li><li><a href="/doc.html#jwt" class="sidebar-link">JWT</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/doc.html#jwt简介" class="sidebar-link">JWT简介</a></li><li class="sidebar-sub-header"><a href="/doc.html#jwt的使用" class="sidebar-link">JWT的使用</a></li></ul></li><li><a href="/doc.html#shiro的其他使用" class="sidebar-link">shiro的其他使用</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/doc.html#自定义shiro错误处理" class="sidebar-link">自定义shiro错误处理</a></li><li class="sidebar-sub-header"><a href="/doc.html#shiro-和-jwt-整合" class="sidebar-link">shiro 和 jwt 整合</a></li><li class="sidebar-sub-header"><a href="/doc.html#shiro-和-sso-整合" class="sidebar-link">shiro 和 sso 整合</a></li></ul></li><li><a href="/doc.html#配置" class="sidebar-link">配置</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/doc.html#高级配置" class="sidebar-link">高级配置</a></li></ul></li><li><a href="/doc.html#model" class="sidebar-link">Model</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/doc.html#table注解" class="sidebar-link">@Table注解</a></li></ul></li><li><a href="/doc.html#db-record-模式" class="sidebar-link">Db + Record 模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#更多" class="sidebar-link">更多</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#多数据源" class="sidebar-link">多数据源</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#分库和分表" class="sidebar-link">分库和分表</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/doc.html#分库" class="sidebar-link">分库</a></li><li class="sidebar-sub-header"><a href="/doc.html#分表" class="sidebar-link">分表</a></li></ul></li><li><a href="/doc.html#google-guice" class="sidebar-link">Google Guice</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#inject-和-bean" class="sidebar-link">@Inject 和 @Bean</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#rpcservice" class="sidebar-link">@RpcService</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/doc.html#使用步骤：" class="sidebar-link">使用步骤：</a></li><li class="sidebar-sub-header"><a href="/doc.html#配置中心" class="sidebar-link">配置中心</a></li></ul></li><li><a href="/doc.html#redis简介" class="sidebar-link">Redis简介</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#redis的使用" class="sidebar-link">Redis的使用</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#redis操作系列方法" class="sidebar-link">Redis操作系列方法</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#redis扩展" class="sidebar-link">Redis扩展</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#redis集群" class="sidebar-link">Redis集群</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#redismq" class="sidebar-link">RedisMQ</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#activemq" class="sidebar-link">ActiveMQ</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/doc.html#使用步骤" class="sidebar-link">使用步骤</a></li><li class="sidebar-sub-header"><a href="/doc.html#注意事项" class="sidebar-link">注意事项</a></li></ul></li><li><a href="/doc.html#ehcache" class="sidebar-link">ehcache</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#redis" class="sidebar-link">redis</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#ehredis" class="sidebar-link">ehredis</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/doc.html#get请求" class="sidebar-link">Get请求</a></li><li class="sidebar-sub-header"><a href="/doc.html#post请求" class="sidebar-link">Post请求</a></li><li class="sidebar-sub-header"><a href="/doc.html#文件上传" class="sidebar-link">文件上传</a></li><li class="sidebar-sub-header"><a href="/doc.html#文件下载" class="sidebar-link">文件下载</a></li><li class="sidebar-sub-header"><a href="/doc.html#添加metric数据" class="sidebar-link">添加metric数据</a></li><li class="sidebar-sub-header"><a href="/doc.html#metric与ganglia" class="sidebar-link">metric与Ganglia</a></li><li class="sidebar-sub-header"><a href="/doc.html#metric与grafana" class="sidebar-link">metric与Grafana</a></li><li class="sidebar-sub-header"><a href="/doc.html#metric与jmx" class="sidebar-link">metric与jmx</a></li><li class="sidebar-sub-header"><a href="/doc.html#hystrix配置" class="sidebar-link">hystrix配置</a></li><li class="sidebar-sub-header"><a href="/doc.html#hystrix-dashboard-部署" class="sidebar-link">Hystrix Dashboard 部署</a></li><li class="sidebar-sub-header"><a href="/doc.html#通过-hystrix-dashboard-查看数据" class="sidebar-link">通过 Hystrix Dashboard 查看数据</a></li><li class="sidebar-sub-header"><a href="/doc.html#自定义监控隔离" class="sidebar-link">自定义监控隔离</a></li><li class="sidebar-sub-header"><a href="/doc.html#opentracing简介" class="sidebar-link">Opentracing简介</a></li><li class="sidebar-sub-header"><a href="/doc.html#opentracing在jboot上的配置" class="sidebar-link">Opentracing在Jboot上的配置</a></li><li class="sidebar-sub-header"><a href="/doc.html#zipkin" class="sidebar-link">Zipkin</a></li><li class="sidebar-sub-header"><a href="/doc.html#skywalking" class="sidebar-link">SkyWalking</a></li><li class="sidebar-sub-header"><a href="/doc.html#其他" class="sidebar-link">其他</a></li></ul></li><li><a href="/doc.html#部署统一配置中心服务器" class="sidebar-link">部署统一配置中心服务器</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#连接统一配置中心" class="sidebar-link">连接统一配置中心</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#swagger简介" class="sidebar-link">swagger简介</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#swagger使用" class="sidebar-link">swagger使用</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/doc.html#第一步：配置并启用swagger" class="sidebar-link">第一步：配置并启用swagger</a></li><li class="sidebar-sub-header"><a href="/doc.html#第二步：下载swagger-ui放到resource目录下" class="sidebar-link">第二步：下载swagger ui放到resource目录下</a></li><li class="sidebar-sub-header"><a href="/doc.html#第三步：通过注解配置controller的api" class="sidebar-link">第三步：通过注解配置Controller的api</a></li><li class="sidebar-sub-header"><a href="/doc.html#第四步：浏览器访问swagger生成api文档" class="sidebar-link">第四步：浏览器访问swagger生成api文档</a></li></ul></li><li><a href="/doc.html#spi扩展" class="sidebar-link">SPI扩展</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/doc.html#spi具体约定" class="sidebar-link">SPI具体约定</a></li><li class="sidebar-sub-header"><a href="/doc.html#jboot-spi模块" class="sidebar-link">Jboot SPI模块</a></li></ul></li><li><a href="/doc.html#jbootevnet事件机制" class="sidebar-link">JbootEvnet事件机制</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#自定义序列化" class="sidebar-link">自定义序列化</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#配置文件" class="sidebar-link">配置文件</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/doc.html#读取jboot-properties的配置信息" class="sidebar-link">读取jboot.properties的配置信息</a></li><li class="sidebar-sub-header"><a href="/doc.html#读取自定义配置文件的配置信息" class="sidebar-link">读取自定义配置文件的配置信息</a></li></ul></li><li><a href="/doc.html#分布式session-2" class="sidebar-link">分布式session</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/doc.html#代码生成器" class="sidebar-link">代码生成器</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/doc.html#使用步骤-2" class="sidebar-link">使用步骤</a></li></ul></li><li><a href="/doc.html#jboot部署到tomcat" class="sidebar-link">Jboot部署到tomcat</a><ul class="sidebar-sub-headers"></ul></li></ul></div></li></ul></div><div class="page"><div class="content"><h1 id="目录"><a href="#目录" aria-hidden="true" class="header-anchor">#</a> 目录</h1><ul><li><p><a href="#%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B">快速上手</a></p></li><li><p><a href="#jboot%E6%A0%B8%E5%BF%83%E7%BB%84%E4%BB%B6">JBoot核心组件</a></p></li><li><p><a href="#mvc">MVC</a></p><ul><li>MVC的概念</li><li>JbootController</li><li>@RquestMapping
<ul><li>使用@RquestMapping</li><li>render</li></ul></li><li>session 与 分布式session</li><li>websocket</li></ul></li><li><p><a href="#%E5%AE%89%E5%85%A8%E6%8E%A7%E5%88%B6">安全控制</a></p><ul><li>shiro简介</li><li>shiro的配置</li><li>shiro的使用
<ul><li>12个模板指令（用在html上）</li><li>5个Requires注解功能（用在Controller上）</li></ul></li></ul></li><li><p><a href="#orm">ORM</a></p><ul><li>配置
<ul><li>高级配置</li></ul></li><li>Model</li><li>@Table注解</li><li>Record</li><li>DAO</li><li>多数据源</li><li>分库和分表
<ul><li>分库</li><li>分表</li></ul></li></ul></li><li><p><a href="#aop">AOP</a></p><ul><li>Google Guice</li><li>@Inject</li><li>@Bean</li></ul></li><li><p><a href="#rpc%E8%BF%9C%E7%A8%8B%E8%B0%83%E7%94%A8">RPC远程调用</a></p><ul><li>使用步骤</li><li>其他注意</li></ul></li><li><p><a href="#redis%E6%93%8D%E4%BD%9C">Redis操作</a></p><ul><li>Redis简介</li><li>Redis的使用</li><li>Redis操作系列方法</li><li>Redis扩展</li><li>Redis集群</li></ul></li><li><p><a href="#mq%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97">MQ消息队列</a></p><ul><li>使用步骤</li><li>RedisMQ</li><li>ActiveMQ</li><li>RabbitMq</li><li>阿里云商业MQ</li></ul></li><li><p><a href="#cache%E7%BC%93%E5%AD%98">Cache缓存</a></p><ul><li>使用步骤</li><li>注意事项</li><li>ehcache</li><li>redis</li><li>ehredis</li></ul></li><li><p><a href="#http%E5%AE%A2%E6%88%B7%E7%AB%AF">http客户端</a></p><ul><li>Get请求</li><li>Post 请求</li><li>文件上传</li><li>文件下载</li></ul></li><li><p><a href="#metrics%E6%95%B0%E6%8D%AE%E7%9B%91%E6%8E%A7">metrics数据监控</a></p><ul><li>添加metric数据</li><li>metric与Ganglia</li><li>metric与grafana</li><li>metric与jmx</li></ul></li><li><p><a href="#%E5%AE%B9%E9%94%99%E4%B8%8E%E9%9A%94%E7%A6%BB">容错与隔离</a></p><ul><li>hystrix配置</li><li>Hystrix Dashboard 部署</li><li>通过 Hystrix Dashboard 查看数据</li></ul></li><li><p><a href="#opentracing%E6%95%B0%E6%8D%AE%E8%BF%BD%E8%B8%AA">Opentracing数据追踪</a></p><ul><li><a href="#opentracing%E7%AE%80%E4%BB%8B">Opentracing简介</a></li><li><a href="#opentracing%E5%9C%A8jboot%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE">Opentracing在Jboot上的配置</a></li><li><a href="#zipkin">Zipkin</a><ul><li><a href="#zipkin%E5%BF%AB%E9%80%9F%E5%90%AF%E5%8A%A8">Zipkin快速启动</a></li><li><a href="#%E4%BD%BF%E7%94%A8zipkin">使用zipkin</a></li></ul></li><li>SkyWalking
<ul><li><a href="#skywalking%E5%BF%AB%E9%80%9F%E5%90%AF%E5%8A%A8">SkyWalking快速启动</a></li><li><a href="#%E4%BD%BF%E7%94%A8skywalking">使用SkyWalking</a></li></ul></li><li>其他</li></ul></li><li><p><a href="#%E7%BB%9F%E4%B8%80%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83">统一配置中心</a></p><ul><li><a href="#%E9%83%A8%E7%BD%B2%E7%BB%9F%E4%B8%80%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%E6%9C%8D%E5%8A%A1%E5%99%A8">部署统一配置中心服务器</a></li><li><a href="#%E8%BF%9E%E6%8E%A5%E7%BB%9F%E4%B8%80%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83">连接统一配置中心</a></li></ul></li><li><p><a href="#swagger-api%E8%87%AA%E5%8A%A8%E7%94%9F%E6%88%90">Swagger api自动生成</a></p><ul><li><a href="#swagger%E7%AE%80%E4%BB%8B">swagger简介</a></li><li><a href="#swagger%E4%BD%BF%E7%94%A8">swagger使用</a></li><li><a href="#swagger%E4%BD%BF%E7%94%A8">5个swagger注解</a></li></ul></li><li><p>其他</p><ul><li><a href="#spi%E6%89%A9%E5%B1%95">SPI扩展</a></li><li><a href="#jbootEvnet%E4%BA%8B%E4%BB%B6%E6%9C%BA%E5%88%B6">JbootEvnet事件机制</a></li><li>自定义序列化</li><li>配置文件</li><li>代码生成器</li></ul></li><li><p><a href="#%E9%A1%B9%E7%9B%AE%E6%9E%84%E5%BB%BA">项目构建</a></p></li><li><p>鸣谢</p></li><li><p><a href="#%E8%81%94%E7%B3%BB%E4%BD%9C%E8%80%85">联系作者</a></p></li><li><p><a href="#%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98">常见问题</a></p><ul><li>使用Jboot后还能自定义JfinalConfig等配置文件吗？</li></ul></li></ul><h1 id="快速上手"><a href="#快速上手" aria-hidden="true" class="header-anchor">#</a> 快速上手</h1><h4 id="创建项目"><a href="#创建项目" aria-hidden="true" class="header-anchor">#</a> 创建项目</h4><p>略</p><h4 id="添加jboot依赖"><a href="#添加jboot依赖" aria-hidden="true" class="header-anchor">#</a> 添加Jboot依赖</h4><pre class="language-xml"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dependency</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>io.jboot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>jboot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">&gt;</span></span>1.4.9<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dependency</span><span class="token punctuation">&gt;</span></span>
</code></pre><h4 id="编写helloworld"><a href="#编写helloworld" aria-hidden="true" class="header-anchor">#</a> 编写helloworld</h4><pre class="language-java"><code><span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MyController</span> <span class="token keyword">extends</span> <span class="token class-name">JbootController</span><span class="token punctuation">{</span>
   <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">index</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token function">renderText</span><span class="token punctuation">(</span><span class="token string">&quot;hello jboot&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span>
   
   <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String <span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span><span class="token punctuation">{</span>
       Jboot<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><h4 id="运行并浏览器查看"><a href="#运行并浏览器查看" aria-hidden="true" class="header-anchor">#</a> 运行并浏览器查看</h4><p>运行main方法后，在浏览器输入网址：http://127.0.0.1:8088 查看，此时，浏览器显示：hello jboot</p><h1 id="jboot核心组件"><a href="#jboot核心组件" aria-hidden="true" class="header-anchor">#</a> JBoot核心组件</h1><p>Jboot的主要核心组件有以下几个。</p><ul><li>[x] MVC （基于jfinal）</li><li>[x] ORM （基于jfinal）</li><li>[x] AOP （基于guice）</li><li>安全控制
<ul><li>[x] shiro</li><li>[x] jwt</li></ul></li><li>RPC远程调用
<ul><li>[x] motan</li><li>[x] dubbo</li><li>[ ] grpc</li></ul></li><li>MQ消息队列
<ul><li>[x] rabbitmq</li><li>[x] redismq</li><li>[x] 阿里云商业MQ</li><li>[ ] activemq</li></ul></li><li>缓存
<ul><li>[x] ehcache</li><li>[x] redis</li><li>[x] 分布式二级缓存ehredis</li></ul></li><li>[x] 分布式session</li><li>[x] 分布式锁</li><li>任务调度
<ul><li>[x] cron4j</li><li>[x] ScheduledThreadPoolExecutor</li><li>[x] 分布式任务调度</li></ul></li><li>[x] 调用监控 (基于metrics)</li><li>[x] 限流、降级、熔断机制（基于hystrix）</li><li>[x] Opentracing数据追踪
<ul><li>[x] zipkin</li><li>[x] skywalking</li></ul></li><li>[x] 统一配置中心</li><li>[x] swagger api</li><li>[x] Http客户端（包含了get、post请求，文件上传和下载等）
<ul><li>[x] httpUrlConnection</li><li>[x] okHttp</li><li>[ ] httpClient</li></ul></li><li>[x] 分布式下的微信和微信第三方</li><li>[x] 自定义序列化组件</li><li>[x] 事件机制</li><li>[x] 代码生成器</li><li>等等</li></ul><h1 id="mvc"><a href="#mvc" aria-hidden="true" class="header-anchor">#</a> MVC</h1><h2 id="mvc的概念"><a href="#mvc的概念" aria-hidden="true" class="header-anchor">#</a> MVC的概念</h2><p>略</p><h2 id="controller"><a href="#controller" aria-hidden="true" class="header-anchor">#</a> Controller</h2><p>Controller是JFinal核心类之一，该类作为MVC模式中的控制器。基于JFinal的Web应用的控制器需要继承该类。Controller是定义Action方法的地点，是组织Action的一种方式，一个Controller可以包含多个Action。Controller是线程安全的。</p><h3 id="jbootcontroller"><a href="#jbootcontroller" aria-hidden="true" class="header-anchor">#</a> JbootController</h3><p>JbootController是扩展了JFinal Controller，在Jboot应用中，所有的控制器都应该继承至JbootController。</p><p><strong>JbootController新增的普通方法：</strong></p><table><thead><tr><th>方法调用</th><th>描述</th></tr></thead><tbody><tr><td>isMoblieBrowser()</td><td>是否是手机浏览器</td></tr><tr><td>isWechatBrowser()</td><td>是否是微信浏览器</td></tr><tr><td>isIEBrowser()</td><td>是否是IE浏览器，低级的IE浏览器在ajax请求的时候，返回json要做特殊处理</td></tr><tr><td>isAjaxRequest()</td><td>是否是ajax请求</td></tr><tr><td>isMultipartRequest()</td><td>是否是带有文件上传功能的请求</td></tr><tr><td>getReferer()</td><td>获取来源网址器</td></tr><tr><td>getIPAddress()</td><td>获取用户的IP地址，这个决定于浏览器，同时做nginx等转发的时候要做好配置</td></tr><tr><td>getUserAgent()</td><td>获取http头的useragent</td></tr><tr><td>getBaseUrl()</td><td>获取当前域名</td></tr><tr><td>getUploadFilesMap()</td><td>获取当前上传的所有文件</td></tr></tbody></table><p><strong>新增关于FlashMessage的方法：</strong></p><table><thead><tr><th>方法调用</th><th>描述</th></tr></thead><tbody><tr><td>setFlashAttr()</td><td>设置 FlashMessage 的 key 和 value</td></tr><tr><td>setFlashMap()</td><td>把整个 map的key和value 设置到 FlashMessage</td></tr><tr><td>getFlashAttr()</td><td>获取 已经设置进去的FlashMessage 信息</td></tr><tr><td>getFlashAttrs()</td><td>获取 所有已经设置进去的 FlashMessage 信息</td></tr></tbody></table><p>FlashMessage 是一种特殊的 attribute，用法和 setAttr 一样，唯一不同的是 setAttr 是用于当前页面渲染，而
setFlashAttr 是用于对 redirect 之后的页面进行渲染。</p><p><strong>新增关于JWT的方法：</strong></p><table><thead><tr><th>方法调用</th><th>描述</th></tr></thead><tbody><tr><td>setJwtAttr()</td><td>设置 jwt 的 key 和 value</td></tr><tr><td>setJwtMap()</td><td>把整个 map的key和value 设置到 jwt</td></tr><tr><td>getJwtAttr()</td><td>获取 已经设置进去的 jwt 信息</td></tr><tr><td>getJwtAttrs()</td><td>获取 所有已经设置进去的 jwt 信息</td></tr><tr><td>getJwtPara()</td><td>获取客户端传进来的 jwt 信息，若 jwt 超时或者不被信任，那么获取到的内容为null</td></tr></tbody></table><p><strong>JWT简介：</strong>  Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准（<a href="https://tools.ietf.org/html/rfc7519" target="_blank" rel="noopener noreferrer">RFC 7519</a>).该token被设计为紧凑且安全的，特别适用于分布式站点的单点登录（SSO）场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息，以便于从资源服务器获取资源，也可以增加一些额外的其它业务逻辑所必须的声明信息，该token也可直接被用于认证，也可被加密。</p><p><em>JWT的相关配置</em></p><table><thead><tr><th>配置属性</th><th>描述</th></tr></thead><tbody><tr><td>jboot.web.jwt.httpHeaderName</td><td>配置JWT的http头的key，默认为JWT</td></tr><tr><td>jboot.web.jwt.secret</td><td>配置JWT的密钥</td></tr><tr><td>jboot.web.jwt.validityPeriod</td><td>配置JWT的过期时间，默认不过期</td></tr></tbody></table><h3 id="rquestmapping"><a href="#rquestmapping" aria-hidden="true" class="header-anchor">#</a> @RquestMapping</h3><p>RquestMapping是请求映射，也就是通过@RquestMapping注解，可以让某个请求映射到指定的控制器Controller里去。</p><p><strong>使用@RquestMapping</strong></p><p>使用@RquestMapping非常简单。只需要在Controller类添加上@RquestMapping注解即可。</p><p>例如：</p><pre class="language-java"><code><span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">HelloController</span> <span class="token keyword">extends</span> <span class="token class-name">JbootController</span><span class="token punctuation">{</span>
   <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">index</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token function">renderText</span><span class="token punctuation">(</span><span class="token string">&quot;hello jboot&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>我们在HelloController控制器上，添加了@RequestMapping(&quot;/&quot;)配置，也就是让当访问 <code>http://127.0.0.1/</code>的时候让HelloController控制的index()这个方法（action）来处理。</p><p><strong>[注意]：</strong></p><ul><li>访问<code>http://127.0.0.1</code>等同于<code>http://127.0.0.1/</code>。</li><li><code>@RquestMapping</code> 可以使用在任何的 Controller，并 <strong>不需要</strong> 这个Controller继承至JbootController。</li></ul><h3 id="action"><a href="#action" aria-hidden="true" class="header-anchor">#</a> Action</h3><p>在 Controller 之中定义的 public 方法称为 Action。Action 是请求的最小单位。Action 方法 必须在 Controller 中定义，且必须是 public 可见性。</p><p>每个Action对应一个URL地址的映射：</p><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">HelloController</span> <span class="token keyword">extends</span> <span class="token class-name">Controller</span> <span class="token punctuation">{</span> 

	<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">index</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token function">renderText</span><span class="token punctuation">(</span><span class="token string">&quot;此方法是一个action&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 
	<span class="token punctuation">}</span>

	<span class="token keyword">public</span> String <span class="token function">test</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> 
		<span class="token keyword">return</span> <span class="token string">&quot;index.html&quot;</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span> 
	
	<span class="token keyword">public</span> String <span class="token function">save</span><span class="token punctuation">(</span>User user<span class="token punctuation">)</span> <span class="token punctuation">{</span> 
		user<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token function">render</span><span class="token punctuation">(</span><span class="token string">&quot;index.html&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span> 
<span class="token punctuation">}</span>
</code></pre><p>以上代码中定义了三个 Action，分别是 <code>HelloController.index()</code>、 <code>HelloController.test()</code> 和 <code>HelloController.save(User user)</code>。</p><p>Action 可以有返回值，返回值可在拦截器中通过 invocation.getReturnValue() 获取到，以便进行 render 控制。</p><p>Action 可以带参数，可以代替 getPara、getBean、getModel 系列方法获取参数，使用 UploadFile 参数时可以代替 getFile 方法实现文件上传。这种传参方式还有一个好处是便于与 swagger 这类 第三方无缝集成，生成 API 文档。</p><p><strong>注意：</strong> 带参数的Action必须在pom.xml文件里添加如下配置：</p><pre class="language-xml"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>plugin</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.apache.maven.plugins<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>maven-compiler-plugin<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>configuration</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>source</span><span class="token punctuation">&gt;</span></span>1.8<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>source</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>target</span><span class="token punctuation">&gt;</span></span>1.8<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>target</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>encoding</span><span class="token punctuation">&gt;</span></span>UTF-8<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>encoding</span><span class="token punctuation">&gt;</span></span>
        <span class="token comment">&lt;!--必须添加compilerArgument配置，才能使用JController方法带参数的功能--&gt;</span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>compilerArgument</span><span class="token punctuation">&gt;</span></span>-parameters<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>compilerArgument</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>configuration</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>plugin</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>如果 action 形参是一个 model 或者 bean，原先通过 getBean(User.class, “”) 获取 时第二个参数为空字符串或 null，那么与之等价的形参注入只需要用一下@Para(“”)注解即可:</p><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">save</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Para</span><span class="token punctuation">(</span>“”<span class="token punctuation">)</span>User user<span class="token punctuation">)</span> <span class="token punctuation">{</span> 
	user<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token function">render</span><span class="token punctuation">(</span><span class="token string">&quot;index.html&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><h3 id="getpara-系列方法"><a href="#getpara-系列方法" aria-hidden="true" class="header-anchor">#</a> getPara 系列方法</h3><p>Controller  供了 getPara 系列方法用来从请求中获取参数。getPara 系列方法分为两种类型。 第一种类型为第一个形参为 String 的 getPara 系列方法。该系列方法是对 HttpServletRequest.getParameter(String name) 的 封 装 ， 这 类 方 法 都 是 转 调 了 HttpServletRequest.getParameter(String name)。第二种类型为第一个形参为 int 或无形参的 getPara 系列方法。该系列方法是去获取 urlPara 中所带的参数值。getParaMap 与 getParaNames 分别对应 HttpServletRequest 的 getParameterMap 与 getParameterNames。</p><table><thead><tr><th>方法调用</th><th>返回值</th></tr></thead><tbody><tr><td>getPara(”title”)</td><td>返回页面表单域名为“title”参数值</td></tr><tr><td>getParaToInt(”age”)</td><td>返回页面表单域名为“age”的参数值并转为 int 型</td></tr><tr><td>getPara(0)</td><td>返回 url 请求中的 urlPara 参数的第一个值，如 http://localhost/controllerKey/method/v0-v1-v2 这个请求将 返回”v0”</td></tr><tr><td>getParaToInt(1)</td><td>返回 url 请求中的 urlPara 参数的第二个值并转换成 int 型，如 http://localhost/controllerKey/method/2-5-9 这个请求将返回 5</td></tr><tr><td>getParaToInt(2)</td><td>如http://localhost/controllerKey/method/2-5-N8 这个 请求将返回 -8。注意:约定字母 N 与 n 可以表示负 号，这对 urlParaSeparator 为 “-” 时非常有用。</td></tr><tr><td>getPara()</td><td>返回 url 请求中的 urlPara 参数的整体值，如 http://localhost/controllerKey/method/v0-v1-v2 这个 请求将返回”v0-v1-v2”</td></tr></tbody></table><h3 id="getbean-与-getmodel-方法"><a href="#getbean-与-getmodel-方法" aria-hidden="true" class="header-anchor">#</a> getBean 与 getModel 方法</h3><p>getModel 用来接收页面表单域传递过来的 model 对象，表单域名称以”modelName.attrName”方式命名，getModel 使用的 attrName 必须与数据表字段名完全一样。getBean 方法用于支持传统 Java Bean，包括支持使用 jfnal 生成器生成了 getter、setter 方法的 Model，页面表单传参时使用与 setter 方法相一致的 attrName，而非数据表字段名。 getModel 与 getBean 区别在于前者使用数表字段名而后者使用与 setter 方法一致的属性名进行数据注入。建议优先使用 getBean 方法。</p><p>以下是一个简单的示例:</p><pre class="language-java"><code><span class="token comment">// 定义Model，在此为Blog</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Blog</span> <span class="token keyword">extends</span> <span class="token class-name">JbootModel</span><span class="token generics function"><span class="token punctuation">&lt;</span>Blog<span class="token punctuation">&gt;</span></span> <span class="token punctuation">{</span>
	
<span class="token punctuation">}</span>

<span class="token comment">// 在页面表单中采用modelName.attrName形式为作为表单域的name </span>
<span class="token operator">&lt;</span>form action<span class="token operator">=</span><span class="token string">&quot;/blog/save&quot;</span> method<span class="token operator">=</span><span class="token string">&quot;post&quot;</span><span class="token operator">&gt;</span>
	<span class="token operator">&lt;</span>input name<span class="token operator">=</span><span class="token string">&quot;blog.title&quot;</span> type<span class="token operator">=</span><span class="token string">&quot;text&quot;</span><span class="token operator">&gt;</span> 
	<span class="token operator">&lt;</span>input name<span class="token operator">=</span><span class="token string">&quot;blog.content&quot;</span> type<span class="token operator">=</span><span class="token string">&quot;text&quot;</span><span class="token operator">&gt;</span> 
	<span class="token operator">&lt;</span>input value<span class="token operator">=</span><span class="token string">&quot; 交&quot;</span> type<span class="token operator">=</span><span class="token string">&quot;submit&quot;</span><span class="token operator">&gt;</span>
<span class="token operator">&lt;</span><span class="token operator">/</span>form<span class="token operator">&gt;</span>

<span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/blog&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">BlogController</span> <span class="token keyword">extends</span> <span class="token class-name">JbootController</span> <span class="token punctuation">{</span> 

	<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">save</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token comment">// 页面的modelName正好是Blog类名的首字母小写 </span>
		Blog blog <span class="token operator">=</span> <span class="token function">getModel</span><span class="token punctuation">(</span>Blog<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		
		<span class="token comment">//如果表单域的名称为 &quot;otherName.title&quot;可加上一个参数来获取</span>
		Blog blog <span class="token operator">=</span> <span class="token function">getModel</span><span class="token punctuation">(</span>Blog<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token string">&quot;otherName&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		
		<span class="token comment">//如果表单域的名称为 &quot;title&quot; 和 &quot;content&quot; </span>
		Blog blog <span class="token operator">=</span> <span class="token function">getModel</span><span class="token punctuation">(</span>Blog<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token string">&quot;&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	
	<span class="token comment">// 或者 也可以写如下代码,但是注意，只能写一个save方法</span>
	<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">save</span><span class="token punctuation">(</span>Blog blog<span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token comment">// do your something</span>
	<span class="token punctuation">}</span>
	
<span class="token punctuation">}</span>
</code></pre><p>上面代码中，表单域采用了”blog.title”、”blog.content”作为表单域的 name 属性，”blog”是类 文件名称”Blog”的首字母变小写，”title”是 blog 数据库表的 title 字段，如果希望表单域使用任 意的 modelName ，只需要在 getModel 时多添加一个参数来指定，例如: getModel(Blog.class, ”otherName”)。</p><h3 id="render"><a href="#render" aria-hidden="true" class="header-anchor">#</a> render</h3><p>渲染器，负责把内容输出到浏览器，在Controller中，提供了如下一些列render方法。</p><table><thead><tr><th>指令</th><th>描述</th></tr></thead><tbody><tr><td>render(”test.html”)</td><td>渲染名为 test.html 的视图，该视图的全路径为”/path/test.html”</td></tr><tr><td>render(”/other_path/test.html”)</td><td>渲染名为 test.html 的视图，该视图的全路径为”/other_path/test.html”，即当参数以”/”开头时将采用绝对路径。</td></tr><tr><td>renderTemplate(”test.html”)</td><td>渲染名为 test.html 的视图，且视图类型为 JFinalTemplate。</td></tr><tr><td>renderFreeMarker(”test.html”)</td><td>渲 染 名 为 test.html 的视图 ， 且 视图类型为FreeMarker。</td></tr><tr><td>renderJsp(”test.jsp”)</td><td>渲染名为 test.jsp 的视图，且视图类型为 Jsp。</td></tr><tr><td>renderVelocity(“test.html”)</td><td>渲染名为 test.html 的视图，且视图类型为 Velocity。</td></tr><tr><td>renderJson()</td><td>将所有通过 Controller.setAttr(String, Object)设置的变量转换成 json 数据并渲染。</td></tr><tr><td>renderJson(“users”, userList)</td><td>以”users”为根，仅将 userList 中的数据转换成 json数据并渲染。</td></tr><tr><td>renderJson(user)</td><td>将 user 对象转换成 json 数据并渲染。</td></tr><tr><td>renderJson(“{\”age\”:18}” )</td><td>直接渲染 json 字符串。</td></tr><tr><td>renderJson(new String[]{“user”, “blog”})</td><td>仅将 setAttr(“user”, user)与 setAttr(“blog”, blog)设置的属性转换成 json 并渲染。使用 setAttr 设置的其它属性并不转换为 json。</td></tr><tr><td>renderFile(“test.zip”);</td><td>渲染名为 test.zip 的文件，一般用于文件下载</td></tr><tr><td>renderText(“Hello Jboot”)</td><td>渲染纯文本内容”Hello Jboot”。</td></tr><tr><td>renderHtml(“Hello Html”)</td><td>渲染 Html 内容”Hello Html”。</td></tr><tr><td>renderError (404 , “test.html”)</td><td>渲染名为 test.html 的文件，且状态为 404。</td></tr><tr><td>renderError (500 , “test.html”)</td><td>渲染名为 test.html 的文件，且状态为 500。</td></tr><tr><td>renderNull()</td><td>不渲染，即不向客户端返回数据。</td></tr><tr><td>render(new MyRender())</td><td>使用自定义渲染器 MyRender 来渲染。</td></tr></tbody></table><h3 id="session-与-分布式session"><a href="#session-与-分布式session" aria-hidden="true" class="header-anchor">#</a> session 与 分布式session</h3><p>使用session非常简单，直接在Controller里调用<code>getSessionAttr(key)</code> 或 <code>setSessionAttr(key,value)</code> 就可以。</p><h4 id="分布式session"><a href="#分布式session" aria-hidden="true" class="header-anchor">#</a> 分布式session</h4><p>在Jboot的设计中，分布式的session是依赖分布式缓存的，jboot中，分布式缓存提供了3种方式：</p><ol><li>ehcache</li><li>redis</li><li>ehredis： 基于ehcache和redis实现的二级缓存框架。</li></ol><p>所以，在使用jboot的分布式session之前，需要在jboot.properties配置上jboot分布式的缓存。</p><p>例如：</p><pre class="language-html"><code>jboot.cache.type=redis
jboot.cache.redis.host = 127.0.0.1
jboot.cache.redis.password = 123456
jboot.cache.redis.database = 1
</code></pre><p>配置好缓存后，直接在Controller里调用<code>getSessionAttr(key)</code> 或 <code>setSessionAttr(key,value)</code> 即可。</p><p><em>注意：</em> session都是走缓存，如果jboot配置的缓存是ehcache（或者 ehredis）,请注意在ehcache.xml上添加名为 <code>SESSION</code> 的缓存节点。</p><h3 id="限流和流量控制"><a href="#限流和流量控制" aria-hidden="true" class="header-anchor">#</a> 限流和流量控制</h3><p>在Jboot中，默认提供了4个注解进行流量管控。4个注解代表着四个不同的流量管控方案，他们分别是：</p><table><thead><tr><th>指令</th><th>描述</th></tr></thead><tbody><tr><td>EnableConcurrencyLimit</td><td>限制当前Action的并发量</td></tr><tr><td>EnablePerIpLimit</td><td>限制每个IP的每秒访问量</td></tr><tr><td>EnablePerUserLimit</td><td>限制每个用户的访问量</td></tr><tr><td>EnableRequestLimit</td><td>限制总体每秒钟可以通过的访问量</td></tr></tbody></table><p>例如：</p><pre class="language-java"><code><span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/limitation&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">LimitationDemo</span> <span class="token keyword">extends</span> <span class="token class-name">JbootController</span> <span class="token punctuation">{</span>


    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        Jboot<span class="token punctuation">.</span><span class="token function">setBootArg</span><span class="token punctuation">(</span><span class="token string">&quot;jboot.limitation.webPath&quot;</span><span class="token punctuation">,</span><span class="token string">&quot;/limitation/view&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        Jboot<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>


    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">index</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">renderText</span><span class="token punctuation">(</span><span class="token string">&quot;render ok&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment">/**
     * 所有的请求，每1秒钟只能访问一次
     */</span>
    <span class="token annotation punctuation">@EnableRequestLimit</span><span class="token punctuation">(</span>rate <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">request</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">renderText</span><span class="token punctuation">(</span><span class="token string">&quot;request() render ok&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment">/**
     * 所有的请求，并发量为1个
     */</span>
    <span class="token annotation punctuation">@EnableConcurrencyLimit</span><span class="token punctuation">(</span>rate <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">con</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">try</span> <span class="token punctuation">{</span>
            Thread<span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">2000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">InterruptedException</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token function">renderText</span><span class="token punctuation">(</span><span class="token string">&quot;con() render ok&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment">/**
     * 所有的请求，每1秒钟只能访问一次
     * 被限制的请求，自动跳转到 /limitation/request2
     */</span>
    <span class="token annotation punctuation">@EnableRequestLimit</span><span class="token punctuation">(</span>rate <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">,</span> renderType <span class="token operator">=</span> LimitRenderType<span class="token punctuation">.</span>REDIRECT<span class="token punctuation">,</span> renderContent <span class="token operator">=</span> <span class="token string">&quot;/limitation/request2&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">request1</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">renderText</span><span class="token punctuation">(</span><span class="token string">&quot;request1() render ok&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>


    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">request2</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">renderText</span><span class="token punctuation">(</span><span class="token string">&quot;request2() render ok&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>


    <span class="token comment">/**
     * 每个用户，每5秒钟只能访问一次
     */</span>
    <span class="token annotation punctuation">@EnablePerUserLimit</span><span class="token punctuation">(</span>rate <span class="token operator">=</span> <span class="token number">0.2</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">user</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">renderText</span><span class="token punctuation">(</span><span class="token string">&quot;user() render ok&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment">/**
     * 每个用户，每5秒钟只能访问一次
     * 被限制的请求，渲染文本内容 &quot;被限制啦&quot;
     */</span>
    <span class="token annotation punctuation">@EnablePerUserLimit</span><span class="token punctuation">(</span>rate <span class="token operator">=</span> <span class="token number">0.2</span><span class="token punctuation">,</span> renderType <span class="token operator">=</span> LimitRenderType<span class="token punctuation">.</span>TEXT<span class="token punctuation">,</span> renderContent <span class="token operator">=</span> <span class="token string">&quot;被限制啦&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">user1</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">renderText</span><span class="token punctuation">(</span><span class="token string">&quot;user1() render ok&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>


    <span class="token comment">/**
     * 每个IP地址，每5秒钟只能访问一次
     */</span>
    <span class="token annotation punctuation">@EnablePerIpLimit</span><span class="token punctuation">(</span>rate <span class="token operator">=</span> <span class="token number">0.2</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">ip</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">renderText</span><span class="token punctuation">(</span><span class="token string">&quot;ip() render ok&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>以上代码和注释已经很清楚的描述了每个注解的意义，但是，针对已经上线的项目，使用@EnableXXXLimit进行流量控制并一定是有效的，很多时候我们需要针对突发流量进行限制和管控，因此，除了以上注解意外，Jboot提供了在线流量管理功能。</p><p>使用Jboot在线流量管理，首先配置上流量管理的URL地址，例如：</p><pre class="language-text"><code>jboot.limitation.webPath = /jboot/limitation
</code></pre><p>配置好，启动项目，访问 <code>http://127.0.0.1:8080/jboot/limitation</code> 我们可以看到如下内容：</p><pre class="language-json"><code><span class="token punctuation">{</span>
<span class="token property">&quot;ipRates&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
	<span class="token property">&quot;/limitation/ip&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
		<span class="token property">&quot;enable&quot;</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
		<span class="token property">&quot;rate&quot;</span><span class="token operator">:</span> <span class="token number">0.2</span><span class="token punctuation">,</span>
		<span class="token property">&quot;renderContent&quot;</span><span class="token operator">:</span> <span class="token string">&quot;&quot;</span><span class="token punctuation">,</span>
		<span class="token property">&quot;renderType&quot;</span><span class="token operator">:</span> <span class="token string">&quot;&quot;</span><span class="token punctuation">,</span>
		<span class="token property">&quot;type&quot;</span><span class="token operator">:</span> <span class="token string">&quot;ip&quot;</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token property">&quot;userRates&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
	<span class="token property">&quot;/limitation/user&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
		<span class="token property">&quot;enable&quot;</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
		<span class="token property">&quot;rate&quot;</span><span class="token operator">:</span> <span class="token number">0.2</span><span class="token punctuation">,</span>
		<span class="token property">&quot;renderContent&quot;</span><span class="token operator">:</span> <span class="token string">&quot;&quot;</span><span class="token punctuation">,</span>
		<span class="token property">&quot;renderType&quot;</span><span class="token operator">:</span> <span class="token string">&quot;&quot;</span><span class="token punctuation">,</span>
		<span class="token property">&quot;type&quot;</span><span class="token operator">:</span> <span class="token string">&quot;user&quot;</span>
	<span class="token punctuation">}</span><span class="token punctuation">,</span>
	<span class="token property">&quot;/limitation/user1&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
		<span class="token property">&quot;enable&quot;</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
		<span class="token property">&quot;rate&quot;</span><span class="token operator">:</span> <span class="token number">0.2</span><span class="token punctuation">,</span>
		<span class="token property">&quot;renderContent&quot;</span><span class="token operator">:</span> <span class="token string">&quot;被限制啦&quot;</span><span class="token punctuation">,</span>
		<span class="token property">&quot;renderType&quot;</span><span class="token operator">:</span> <span class="token string">&quot;text&quot;</span><span class="token punctuation">,</span>
		<span class="token property">&quot;type&quot;</span><span class="token operator">:</span> <span class="token string">&quot;user&quot;</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token property">&quot;concurrencyRates&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
	<span class="token property">&quot;/limitation/con&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
		<span class="token property">&quot;enable&quot;</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
		<span class="token property">&quot;rate&quot;</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
		<span class="token property">&quot;renderContent&quot;</span><span class="token operator">:</span> <span class="token string">&quot;&quot;</span><span class="token punctuation">,</span>
		<span class="token property">&quot;renderType&quot;</span><span class="token operator">:</span> <span class="token string">&quot;&quot;</span><span class="token punctuation">,</span>
		<span class="token property">&quot;type&quot;</span><span class="token operator">:</span> <span class="token string">&quot;concurrency&quot;</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token property">&quot;requestRates&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
	<span class="token property">&quot;/limitation/request1&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
		<span class="token property">&quot;enable&quot;</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
		<span class="token property">&quot;rate&quot;</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
		<span class="token property">&quot;renderContent&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/limitation/request2&quot;</span><span class="token punctuation">,</span>
		<span class="token property">&quot;renderType&quot;</span><span class="token operator">:</span> <span class="token string">&quot;redirect&quot;</span><span class="token punctuation">,</span>
		<span class="token property">&quot;type&quot;</span><span class="token operator">:</span> <span class="token string">&quot;request&quot;</span>
	<span class="token punctuation">}</span><span class="token punctuation">,</span>
	<span class="token property">&quot;/limitation/request&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
		<span class="token property">&quot;enable&quot;</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
		<span class="token property">&quot;rate&quot;</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
		<span class="token property">&quot;renderContent&quot;</span><span class="token operator">:</span> <span class="token string">&quot;&quot;</span><span class="token punctuation">,</span>
		<span class="token property">&quot;renderType&quot;</span><span class="token operator">:</span> <span class="token string">&quot;&quot;</span><span class="token punctuation">,</span>
		<span class="token property">&quot;type&quot;</span><span class="token operator">:</span> <span class="token string">&quot;request&quot;</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><h4 id="限流api"><a href="#限流api" aria-hidden="true" class="header-anchor">#</a> 限流API</h4><ol><li><p>限流设置</p><ul><li><p>接口：<code>/jboot/limitation/set</code></p></li><li><p>参数：</p><table><thead><tr><th>描述</th></tr></thead><tbody><tr><td>pe</td></tr><tr><td>th</td></tr><tr><td>te</td></tr></tbody></table></li></ul></li><li><p>关闭限流管控</p><ul><li><p>接口：<code>/jboot/limitation/close</code></p></li><li><p>参数：</p><table><thead><tr><th>描述</th></tr></thead><tbody><tr><td>pe</td></tr><tr><td>th</td></tr></tbody></table></li></ul></li><li><p>开启限流管控</p><ul><li><p>接口：<code>/jboot/limitation/enable</code></p></li><li><p>参数：</p><table><thead><tr><th>描述</th></tr></thead><tbody><tr><td>pe</td></tr><tr><td>th</td></tr></tbody></table></li></ul></li></ol><p><strong>注意：</strong></p><ol><li>通过限流API进行限流，所有的设置都会保存在内存里，因此如果重启服务器后，通过限流API进行限流的所有设置将会失效。</li><li>接口的前缀 <code>/jboot/limitation</code>是通过jboot.properties的<code>jboot.limitation.webPath = /jboot/limitation</code>进行设置的。</li></ol><p><strong>限流API安全设置</strong></p><p>由于限流功能对系统至关重要，为了防止恶意用户猜出限流API对系统进行恶意操作，因此Jboot提供了限流API的权限设置功能，需要通过 通过jboot.properties的<code>jboot.limitation.webAuthorizer = com.xxx.MyAuthorizer</code>进行设置，其中<code>MyAuthorizer</code>需要实现<code>io.jboot.web.limitation.web.Authorizer</code>接口。</p><p>例如：</p><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MyAuthorizer</span> <span class="token keyword">implements</span> <span class="token class-name">Authorizer</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">onAuthorize</span><span class="token punctuation">(</span>Controller controller<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>当限流API被请求的时候，会通过 <code>MyAuthorizer</code> 进行权限认证，只有<code>MyAuthorizer</code>通过(onAuthorize返回<code>true</code>)的时候，请求API才会生效。</p><h2 id="websocket"><a href="#websocket" aria-hidden="true" class="header-anchor">#</a> websocket</h2><p>在使用websocket之前，需要在jboot.properties文件上配置启动websocket，例如：</p><pre class="language-java"><code>jboot<span class="token punctuation">.</span>web<span class="token punctuation">.</span>websocketEnable <span class="token operator">=</span> <span class="token boolean">true</span>
jboot<span class="token punctuation">.</span>web<span class="token punctuation">.</span>websocketBufferPoolSize <span class="token operator">=</span> <span class="token number">100</span>  
</code></pre><p><code>jboot.web.websocketBufferPoolSize</code> 在没有配置的情况下，默认值是<code>100</code>。</p><p>当做好以上配置后，就可以开始编写websocket的相关代码了。</p><p>html代码：</p><pre class="language-html"><code><span class="token doctype">&lt;!DOCTYPE html&gt;</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>UTF-8<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">&gt;</span></span>Insert title here<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>
服务器返回的信息：
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>text<span class="token punctuation">&quot;</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>show<span class="token punctuation">&quot;</span></span><span class="token punctuation">/&gt;</span></span>

浏览器发送的信息：
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>text<span class="token punctuation">&quot;</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>msg<span class="token punctuation">&quot;</span></span><span class="token punctuation">/&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>button<span class="token punctuation">&quot;</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>send<span class="token punctuation">&quot;</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>send<span class="token punctuation">&quot;</span></span> <span class="token attr-name">onclick</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>send()<span class="token punctuation">&quot;</span></span><span class="token punctuation">/&gt;</span></span>


<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">
    <span class="token keyword">var</span> ws <span class="token operator">=</span> <span class="token keyword">null</span> <span class="token punctuation">;</span>
    <span class="token keyword">var</span> target<span class="token operator">=</span><span class="token string">&quot;ws://localhost:8080/websocket/test&quot;</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token string">'WebSocket'</span> <span class="token keyword">in</span> window<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        ws <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">WebSocket</span><span class="token punctuation">(</span>target<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token string">'MozWebSocket'</span> <span class="token keyword">in</span> window<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        ws <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MozWebSocket</span><span class="token punctuation">(</span>target<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">'WebSocket is not supported by this browser.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    ws<span class="token punctuation">.</span><span class="token function-variable function">onopen</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">{</span>
        console<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">'open'</span><span class="token punctuation">)</span> <span class="token punctuation">;</span>
        console<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span> <span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token punctuation">;</span>
    
    ws<span class="token punctuation">.</span><span class="token function-variable function">onclose</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>obj<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        console<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">'close'</span><span class="token punctuation">)</span> <span class="token punctuation">;</span>
        console<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span> <span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token punctuation">;</span>
    ws<span class="token punctuation">.</span><span class="token function-variable function">onmessage</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">{</span>
        console<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span> <span class="token punctuation">;</span>
        document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'show'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>value<span class="token operator">=</span>obj<span class="token punctuation">.</span>data<span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token punctuation">;</span>
    <span class="token keyword">function</span> <span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
    	ws<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'msg'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>java代码：</p><pre class="language-java"><code><span class="token annotation punctuation">@ServerEndpoint</span><span class="token punctuation">(</span><span class="token string">&quot;/websocket/test&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Test</span> <span class="token punctuation">{</span>
	<span class="token annotation punctuation">@OnOpen</span>
	<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onOpen</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
		System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">&quot;onOpen&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token annotation punctuation">@OnClose</span>
	<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onClose</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
		System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">&quot;onClose&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token annotation punctuation">@OnMessage</span>
	<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onMessage</span><span class="token punctuation">(</span>Session session<span class="token punctuation">,</span>String msg<span class="token punctuation">)</span><span class="token punctuation">{</span>
		System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">&quot;receive message : &quot;</span><span class="token operator">+</span>msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">if</span><span class="token punctuation">(</span>session<span class="token punctuation">.</span><span class="token function">isOpen</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
			<span class="token keyword">try</span> <span class="token punctuation">{</span>
				<span class="token comment">//发送消息的html页面</span>
				session<span class="token punctuation">.</span><span class="token function">getBasicRemote</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">sendText</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">IOException</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
				e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><h1 id="安全控制"><a href="#安全控制" aria-hidden="true" class="header-anchor">#</a> 安全控制</h1><h2 id="shiro简介"><a href="#shiro简介" aria-hidden="true" class="header-anchor">#</a> shiro简介</h2><p>Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。</p><h2 id="shiro的配置"><a href="#shiro的配置" aria-hidden="true" class="header-anchor">#</a> shiro的配置</h2><p>在使用Jboot的shiro模块之前，我假定您已经学习并了解shiro的基础知识。在Jboot中使用shiro非常简单，只需要在resources目录下配置上您的shiro.ini文件即可。在shiro.ini文件里，需要在自行扩展realm等信息。</p><h2 id="shiro的使用"><a href="#shiro的使用" aria-hidden="true" class="header-anchor">#</a> shiro的使用</h2><p>Jboot的shiro模块为您提供了以下12个模板指令，同时支持shiro的5个Requires注解功能。方便您使用shiro。</p><h3 id="_12个模板指令（用在html上）"><a href="#_12个模板指令（用在html上）" aria-hidden="true" class="header-anchor">#</a> 12个模板指令（用在html上）</h3><table><thead><tr><th>指令</th><th>描述</th></tr></thead><tbody><tr><td>shiroAuthenticated</td><td>用户已经身份验证通过，Subject.login登录成功</td></tr><tr><td>shiroGuest</td><td>游客访问时。 但是，当用户登录成功了就不显示了</td></tr><tr><td>shiroHasAllPermission</td><td>拥有全部权限</td></tr><tr><td>shiroHasAllRoles</td><td>拥有全部角色</td></tr><tr><td>shiroHasAnyPermission</td><td>拥有任何一个权限</td></tr><tr><td>shiroHasAnyRoles</td><td>拥有任何一个角色</td></tr><tr><td>shiroHasPermission</td><td>有相应权限</td></tr><tr><td>shiroHasRole</td><td>有相应角色</td></tr><tr><td>shiroNoAuthenticated</td><td>未进行身份验证时，即没有调用Subject.login进行登录。</td></tr><tr><td>shiroNotHasPermission</td><td>没有该权限</td></tr><tr><td>shiroNotHasRole</td><td>没有该角色</td></tr><tr><td>shiroPrincipal</td><td>获取Subject Principal 身份信息</td></tr></tbody></table><h4 id="shiroauthenticated的使用"><a href="#shiroauthenticated的使用" aria-hidden="true" class="header-anchor">#</a> shiroAuthenticated的使用</h4><pre class="language-html"><code>#shiroAuthenticated()
  登陆成功：您的用户名是：#(SESSION(&quot;username&quot;))
#end

</code></pre><h4 id="shiroguest的使用"><a href="#shiroguest的使用" aria-hidden="true" class="header-anchor">#</a> shiroGuest的使用</h4><pre class="language-html"><code>#shiroGuest()
  游客您好
#end

</code></pre><h4 id="shirohasallpermission的使用"><a href="#shirohasallpermission的使用" aria-hidden="true" class="header-anchor">#</a> shiroHasAllPermission的使用</h4><pre class="language-html"><code>#shiroHasAllPermission(permissionName1,permissionName2)
  您好，您拥有了权限 permissionName1和permissionName2
#end

</code></pre><h4 id="shirohasallroles的使用"><a href="#shirohasallroles的使用" aria-hidden="true" class="header-anchor">#</a> shiroHasAllRoles的使用</h4><pre class="language-html"><code>#shiroHasAllRoles(role1, role2)
  您好，您拥有了角色 role1和role2
#end

</code></pre><h4 id="shirohasanypermission的使用"><a href="#shirohasanypermission的使用" aria-hidden="true" class="header-anchor">#</a> shiroHasAnyPermission的使用</h4><pre class="language-html"><code>#shiroHasAnyPermission(permissionName1,permissionName2)
  您好，您拥有了权限 permissionName1 或 permissionName2 
#end

</code></pre><h4 id="shirohasanyroles的使用"><a href="#shirohasanyroles的使用" aria-hidden="true" class="header-anchor">#</a> shiroHasAnyRoles的使用</h4><pre class="language-html"><code>#shiroHasAllRoles(role1, role2)
  您好，您拥有了角色 role1 或 role2
#end

</code></pre><h4 id="shirohaspermission的使用"><a href="#shirohaspermission的使用" aria-hidden="true" class="header-anchor">#</a> shiroHasPermission的使用</h4><pre class="language-html"><code>#shiroHasPermission(permissionName1)
  您好，您拥有了权限 permissionName1 
#end

</code></pre><h4 id="shirohasrole的使用"><a href="#shirohasrole的使用" aria-hidden="true" class="header-anchor">#</a> shiroHasRole的使用</h4><pre class="language-html"><code>#shiroHasRole(role1)
  您好，您拥有了角色 role1 
#end

</code></pre><h4 id="shironoauthenticated的使用"><a href="#shironoauthenticated的使用" aria-hidden="true" class="header-anchor">#</a> shiroNoAuthenticated的使用</h4><pre class="language-html"><code>#shiroNoAuthenticated()
  您好，您还没有登陆
#end

</code></pre><h4 id="shironothaspermission的使用"><a href="#shironothaspermission的使用" aria-hidden="true" class="header-anchor">#</a> shiroNotHasPermission的使用</h4><pre class="language-html"><code>#shiroNotHasPermission(permissionName1)
  您好，您没有权限 permissionName1 
#end

</code></pre><h4 id="shironothasrole的使用"><a href="#shironothasrole的使用" aria-hidden="true" class="header-anchor">#</a> shiroNotHasRole的使用</h4><pre class="language-html"><code>#shiroNotHasRole(role1)
  您好，您没有角色role1
#end

</code></pre><h4 id="shiroprincipal的使用"><a href="#shiroprincipal的使用" aria-hidden="true" class="header-anchor">#</a> shiroPrincipal的使用</h4><pre class="language-html"><code>#shiroPrincipal()
  您好，您的登陆信息是：#(principal)
#end

</code></pre><h3 id="_5个requires注解功能（用在controller上）"><a href="#_5个requires注解功能（用在controller上）" aria-hidden="true" class="header-anchor">#</a> 5个Requires注解功能（用在Controller上）</h3><table><thead><tr><th>指令</th><th>描述</th></tr></thead><tbody><tr><td>RequiresPermissions</td><td>需要权限才能访问这个action</td></tr><tr><td>RequiresRoles</td><td>需要角色才能访问这个action</td></tr><tr><td>RequiresAuthentication</td><td>需要授权才能访问这个action，即：<code>SecurityUtils.getSubject().isAuthenticated()</code></td></tr><tr><td>RequiresUser</td><td>获取到用户信息才能访问这个action，即：<code>SecurityUtils.getSubject().getPrincipal() != null</code></td></tr><tr><td>RequiresGuest</td><td>和RequiresUser相反</td></tr></tbody></table><h4 id="requirespermissions的使用"><a href="#requirespermissions的使用" aria-hidden="true" class="header-anchor">#</a> RequiresPermissions的使用</h4><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MyController</span> <span class="token keyword">extends</span> <span class="token class-name">JbootController</span><span class="token punctuation">{</span>

      <span class="token annotation punctuation">@RequiresPermissions</span><span class="token punctuation">(</span><span class="token string">&quot;permission1&quot;</span><span class="token punctuation">)</span>
      <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">index</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>

	  <span class="token punctuation">}</span>
	  
	  <span class="token annotation punctuation">@RequiresPermissions</span><span class="token punctuation">(</span>value<span class="token operator">=</span><span class="token punctuation">{</span><span class="token string">&quot;permission1&quot;</span><span class="token punctuation">,</span><span class="token string">&quot;permission2&quot;</span><span class="token punctuation">}</span><span class="token punctuation">,</span>logical<span class="token operator">=</span>Logincal<span class="token punctuation">.</span>AND<span class="token punctuation">)</span>
      <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">index1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>

	  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><h4 id="requiresroles的使用"><a href="#requiresroles的使用" aria-hidden="true" class="header-anchor">#</a> RequiresRoles的使用</h4><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MyController</span> <span class="token keyword">extends</span> <span class="token class-name">JbootController</span><span class="token punctuation">{</span>

      <span class="token annotation punctuation">@RequiresRoles</span><span class="token punctuation">(</span><span class="token string">&quot;role1&quot;</span><span class="token punctuation">)</span>
      <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">index</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>

	  <span class="token punctuation">}</span>
	  
	  <span class="token annotation punctuation">@RequiresRoles</span><span class="token punctuation">(</span>value <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token string">&quot;role1&quot;</span><span class="token punctuation">,</span><span class="token string">&quot;role2&quot;</span><span class="token punctuation">}</span><span class="token punctuation">,</span>logical<span class="token operator">=</span>Logincal<span class="token punctuation">.</span>AND<span class="token punctuation">)</span>
      <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">userctener</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>

	  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><h4 id="requiresuser、requiresguest、requiresauthentication的使用"><a href="#requiresuser、requiresguest、requiresauthentication的使用" aria-hidden="true" class="header-anchor">#</a> RequiresUser、RequiresGuest、RequiresAuthentication的使用</h4><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MyController</span> <span class="token keyword">extends</span> <span class="token class-name">JbootController</span><span class="token punctuation">{</span>

      <span class="token annotation punctuation">@RequiresUser</span>
      <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">userCenter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>

	  <span class="token punctuation">}</span>
	  
	  <span class="token annotation punctuation">@RequiresGuest</span>
      <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">login</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>

	  <span class="token punctuation">}</span>
	  
	  <span class="token annotation punctuation">@RequiresAuthentication</span>
	  <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">my</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
	  
	  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><h2 id="jwt"><a href="#jwt" aria-hidden="true" class="header-anchor">#</a> JWT</h2><h3 id="jwt简介"><a href="#jwt简介" aria-hidden="true" class="header-anchor">#</a> JWT简介</h3><p>Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准（<a href="https://tools.ietf.org/html/rfc7519" target="_blank" rel="noopener noreferrer">RFC 7519</a>).该token被设计为紧凑且安全的，特别适用于分布式站点的单点登录（SSO）场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息，以便于从资源服务器获取资源，也可以增加一些额外的其它业务逻辑所必须的声明信息，该token也可直接被用于认证，也可被加密。</p><h3 id="jwt的使用"><a href="#jwt的使用" aria-hidden="true" class="header-anchor">#</a> JWT的使用</h3><h4 id="在server段使用jwt"><a href="#在server段使用jwt" aria-hidden="true" class="header-anchor">#</a> 在server段使用JWT</h4><p>在Server端使用JWT非常简单，代码如下：</p><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">JwtController</span> <span class="token keyword">extends</span> <span class="token class-name">JbootController</span> <span class="token punctuation">{</span>

    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">index</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">setJwtAttr</span><span class="token punctuation">(</span><span class="token string">&quot;key1&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;test1&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">setJwtAttr</span><span class="token punctuation">(</span><span class="token string">&quot;key2&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;test2&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        
        <span class="token comment">//do your sth</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">show</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        String value <span class="token operator">=</span> <span class="token function">getJwtPara</span><span class="token punctuation">(</span><span class="token string">&quot;key1&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// value : test1</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p><strong>注意：</strong> 在Server端使用JWT，必须在jboot.properties配置文件中配置上 jwt 的秘钥，代码如下：</p><pre class="language-java"><code>jboot<span class="token punctuation">.</span>web<span class="token punctuation">.</span>jwt<span class="token punctuation">.</span>secret <span class="token operator">=</span> your_secret
</code></pre><p><strong>关于JWT的方法：</strong></p><table><thead><tr><th>方法调用</th><th>描述</th></tr></thead><tbody><tr><td>setJwtAttr()</td><td>设置 jwt 的 key 和 value</td></tr><tr><td>setJwtMap()</td><td>把整个 map的key和value 设置到 jwt</td></tr><tr><td>getJwtAttr()</td><td>获取 已经设置进去的 jwt 信息</td></tr><tr><td>getJwtAttrs()</td><td>获取 所有已经设置进去的 jwt 信息</td></tr><tr><td>getJwtPara()</td><td>获取客户端传进来的 jwt 信息，若 jwt 超时或者不被信任，那么获取到的内容为null</td></tr></tbody></table><h4 id="在客户端使用jwt"><a href="#在客户端使用jwt" aria-hidden="true" class="header-anchor">#</a> 在客户端使用JWT</h4><p>在客户端使用JWT的场景一般是用于非浏览器的第三方进行认证，例如：APP客户端，前后端分离的AJAX请求等。</p><p>例如，在登录后，服务器Server会通过 <code>setJwtAttr()</code> 设置上用户数据，客户端可以去获取 HTTP 响应头中的 Jwt，就可以获取 服务器渲染的 Jwt 信息，此时，应该把 Jwt 的信息保存下来，比如保存到 cookie 或 保存在storage等，
在客户每次请求服务器 API 的时候，应该把 Jwt 设置在请求的 http 头中的 Jwt（注意，第一个字母大写），服务器就可以获取到具体是哪个 “用户” 进行请求了。</p><h2 id="shiro的其他使用"><a href="#shiro的其他使用" aria-hidden="true" class="header-anchor">#</a> shiro的其他使用</h2><h3 id="自定义shiro错误处理"><a href="#自定义shiro错误处理" aria-hidden="true" class="header-anchor">#</a> 自定义shiro错误处理</h3><p>编写一个类实现 实现接口 io.jboot.component.shiro.JbootShiroInvokeListener，例如：</p><pre class="language-java"><code>  <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MyshiroListener</span> <span class="token keyword">implements</span>  <span class="token class-name">JbootShiroInvokeListener</span> <span class="token punctuation">{</span>


        <span class="token keyword">private</span> JbootShiroConfig config <span class="token operator">=</span> Jboot<span class="token punctuation">.</span><span class="token function">config</span><span class="token punctuation">(</span>JbootShiroConfig<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>


        <span class="token annotation punctuation">@Override</span>
        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onInvokeBefore</span><span class="token punctuation">(</span>FixedInvocation inv<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token comment">//do nothing</span>
        <span class="token punctuation">}</span>

        <span class="token annotation punctuation">@Override</span>
        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onInvokeAfter</span><span class="token punctuation">(</span>FixedInvocation inv<span class="token punctuation">,</span> AuthorizeResult result<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>result <span class="token operator">==</span> null <span class="token operator">||</span> result<span class="token punctuation">.</span><span class="token function">isOk</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                inv<span class="token punctuation">.</span><span class="token function">invoke</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword">return</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>

            <span class="token keyword">int</span> errorCode <span class="token operator">=</span> result<span class="token punctuation">.</span><span class="token function">getErrorCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">switch</span> <span class="token punctuation">(</span>errorCode<span class="token punctuation">)</span> <span class="token punctuation">{</span>
                <span class="token keyword">case</span> AuthorizeResult<span class="token punctuation">.</span>ERROR_CODE_UNAUTHENTICATED<span class="token operator">:</span>
                    <span class="token function">doProcessUnauthenticated</span><span class="token punctuation">(</span>inv<span class="token punctuation">.</span><span class="token function">getController</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">break</span><span class="token punctuation">;</span>
                <span class="token keyword">case</span> AuthorizeResult<span class="token punctuation">.</span>ERROR_CODE_UNAUTHORIZATION<span class="token operator">:</span>
                    <span class="token function">doProcessuUnauthorization</span><span class="token punctuation">(</span>inv<span class="token punctuation">.</span><span class="token function">getController</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">break</span><span class="token punctuation">;</span>
                <span class="token keyword">default</span><span class="token operator">:</span>
                    inv<span class="token punctuation">.</span><span class="token function">getController</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">renderError</span><span class="token punctuation">(</span><span class="token number">404</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>


        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">doProcessUnauthenticated</span><span class="token punctuation">(</span>Controller controller<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token comment">// 处理认证失败</span>
        <span class="token punctuation">}</span>

        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">doProcessuUnauthorization</span><span class="token punctuation">(</span>Controller controller<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token comment">// 处理授权失败</span>
        <span class="token punctuation">}</span>

    <span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre><p>其次在jboot.properties中配置即可</p><pre class="language-xml"><code>jboot.shiro.invokeListener=com.xxx.MyshiroListener
</code></pre><h3 id="shiro-和-jwt-整合"><a href="#shiro-和-jwt-整合" aria-hidden="true" class="header-anchor">#</a> shiro 和 jwt 整合</h3><p>和自定义shiro错误处理一样。 编写一个类实现 实现接口 io.jboot.component.shiro.JbootShiroInvokeListener，例如：</p><pre class="language-java"><code>  <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MyshiroListener</span> <span class="token keyword">implements</span>  <span class="token class-name">JbootShiroInvokeListener</span> <span class="token punctuation">{</span>

        <span class="token annotation punctuation">@Override</span>
        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onInvokeBefore</span><span class="token punctuation">(</span>FixedInvocation inv<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            String userId <span class="token operator">=</span> String<span class="token punctuation">.</span><span class="token function">valueOf</span><span class="token punctuation">(</span>inv<span class="token punctuation">.</span>getController<span class="token punctuation">.</span><span class="token function">getJwtPara</span><span class="token punctuation">(</span>USER_ID<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

            JwtAuthenticationToken token <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">JwtAuthenticationToken</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            token<span class="token punctuation">.</span><span class="token function">setUserId</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span><span class="token punctuation">;</span>
            token<span class="token punctuation">.</span><span class="token function">setToken</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span><span class="token punctuation">;</span>
    
            Subject subject <span class="token operator">=</span> SecurityUtils<span class="token punctuation">.</span><span class="token function">getSubject</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            subject<span class="token punctuation">.</span><span class="token function">login</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span>
    
            <span class="token keyword">return</span> subject<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token annotation punctuation">@Override</span>
        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onInvokeAfter</span><span class="token punctuation">(</span>FixedInvocation inv<span class="token punctuation">,</span> AuthorizeResult result<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token comment">// ....</span>
        <span class="token punctuation">}</span>

    <span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre><p>同时在jboot.properties中配置即可</p><pre class="language-xml"><code>jboot.shiro.invokeListener=com.xxx.MyshiroListener
</code></pre><p>自定义JwtAuthenticationToken</p><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">JwtAuthenticationToken</span> <span class="token keyword">implements</span> <span class="token class-name">AuthenticationToken</span> <span class="token punctuation">{</span>
    <span class="token comment">/** 用户id */</span>
    <span class="token keyword">private</span> String userId<span class="token punctuation">;</span>
    <span class="token comment">/** token */</span>
    <span class="token keyword">private</span> String token<span class="token punctuation">;</span>
    
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> Object <span class="token function">getPrincipal</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> userId<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> Object <span class="token function">getCredentials</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> token<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> getter setter
<span class="token punctuation">}</span>
</code></pre><p>实现shiro realm JwtAuthorizingRealm</p><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">JwtAuthorizingRealm</span> <span class="token keyword">extends</span> <span class="token class-name">AuthorizingRealm</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">supports</span><span class="token punctuation">(</span>AuthenticationToken token<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> token <span class="token keyword">instanceof</span> <span class="token class-name">JwtAuthenticationToken</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">protected</span> AuthenticationInfo <span class="token function">doGetAuthenticationInfo</span><span class="token punctuation">(</span>AuthenticationToken token<span class="token punctuation">)</span> <span class="token keyword">throws</span> AuthenticationException <span class="token punctuation">{</span>
        JwtAuthenticationToken jwtToken <span class="token operator">=</span> <span class="token punctuation">(</span>JwtAuthenticationToken<span class="token punctuation">)</span> token<span class="token punctuation">;</span>
        String uid <span class="token operator">=</span> <span class="token punctuation">(</span>String<span class="token punctuation">)</span> jwtToken<span class="token punctuation">.</span><span class="token function">getPrincipal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// 此处判断 uid 是否存在，可以访问等操作</span>
       
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">SimpleAuthenticationInfo</span><span class="token punctuation">(</span>uid<span class="token punctuation">,</span> jwtToken<span class="token punctuation">.</span><span class="token function">getCredentials</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">protected</span> AuthorizationInfo <span class="token function">doGetAuthorizationInfo</span><span class="token punctuation">(</span>PrincipalCollection principals<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// 此处获取 uid 角色权限</span>
        <span class="token keyword">return</span> null<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>实现jwt 无状态化，JwtSubjectFactory</p><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">JwtSubjectFactory</span> <span class="token keyword">extends</span> <span class="token class-name">DefaultWebSubjectFactory</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> Subject <span class="token function">createSubject</span><span class="token punctuation">(</span>SubjectContext context<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">getAuthenticationToken</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">instanceof</span> <span class="token class-name">JwtAuthenticationToken</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token comment">// jwt 不创建 session</span>
            context<span class="token punctuation">.</span><span class="token function">setSessionCreationEnabled</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token keyword">return</span> <span class="token keyword">super</span><span class="token punctuation">.</span><span class="token function">createSubject</span><span class="token punctuation">(</span>context<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>jboot.properties中配置</p><pre class="language-xml"><code>#---------------------------------------------------------------------------------#
jboot.web.jwt.httpHeaderName=Jwt
jboot.web.jwt.secret=xxxxxxxxx
jboot.web.jwt.validityPeriod=1800000
#---------------------------------------------------------------------------------#```
</code></pre><p>shiro.ini中配置</p><pre class="language-xml"><code>
    [main]
    #cache Manager
    shiroCacheManager = io.jboot.component.shiro.cache.JbootShiroCacheManager
    securityManager.cacheManager = $shiroCacheManager

    #realm
    dbRealm=xxx.JwtAuthorizingRealm
    dbRealm.authorizationCacheName=shiro-authorizationCache
    
    securityManager.realm=$dbRealm

    #session manager
    sessionManager=org.apache.shiro.session.mgt.DefaultSessionManager
    sessionManager.sessionValidationSchedulerEnabled=false

    #use jwt
    subjectFactory=xxx.JwtSubjectFactory
    securityManager.subjectFactory=$subjectFactory
    securityManager.sessionManager=$sessionManager

    #session storage false
    securityManager.subjectDAO.sessionStorageEvaluator.sessionStorageEnabled=false
    
</code></pre><h4 id="认证服务端配置"><a href="#认证服务端配置" aria-hidden="true" class="header-anchor">#</a> 认证服务端配置</h4><p>服务端主要作用为对用户名密码做认证，通过后构建jwt，与正常认证无太大区别，所以下面只给出认证后构建jwt的demo</p><pre class="language-java"><code><span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MainController</span> <span class="token keyword">extends</span> <span class="token class-name">BaseController</span> <span class="token punctuation">{</span>

    <span class="token comment">/**
     * 登录 基于 jwt
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">postLogin</span><span class="token punctuation">(</span>String loginName<span class="token punctuation">,</span> String pwd<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// 此处判断用户名密码是否正确</span>
        
        String userId <span class="token operator">=</span> <span class="token string">&quot;userId&quot;</span><span class="token punctuation">;</span> <span class="token comment">//返回用户ID</span>
        <span class="token function">setJwtAttr</span><span class="token punctuation">(</span><span class="token string">&quot;userId&quot;</span><span class="token punctuation">,</span> userId<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//构建jwt</span>
        <span class="token function">renderJson</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//返回成功</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><h3 id="shiro-和-sso-整合"><a href="#shiro-和-sso-整合" aria-hidden="true" class="header-anchor">#</a> shiro 和 sso 整合</h3><p>和上面介绍的 jwt 的桥接器类似，主要作用是接收 sso 请求，完成客户端应用的局部认证与授权。</p><p>以下是一个基于jboot 实现 sso服务端 与 sso客户端的 demo</p><h4 id="sso客户端配置"><a href="#sso客户端配置" aria-hidden="true" class="header-anchor">#</a> SSO客户端配置</h4><p>自定义 SSOAuthenticationToken</p><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">SSOAuthenticationToken</span> <span class="token keyword">implements</span> <span class="token class-name">AuthenticationToken</span> <span class="token punctuation">{</span>

    <span class="token comment">/** 用户id */</span>
    <span class="token keyword">private</span> String userId<span class="token punctuation">;</span>

    <span class="token comment">/** 全局会话 code */</span>
    <span class="token keyword">private</span> String ssoCode<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> Object <span class="token function">getPrincipal</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> userId<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> Object <span class="token function">getCredentials</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> ssoCode<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> getter setter
</code></pre><p>实现 JbootShiroInvokeListener 接口：</p><pre class="language-java"><code> <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MyshiroListener</span> <span class="token keyword">implements</span>  <span class="token class-name">JbootShiroInvokeListener</span> <span class="token punctuation">{</span>

        <span class="token annotation punctuation">@Override</span>
        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onInvokeBefore</span><span class="token punctuation">(</span>FixedInvocation inv<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        String ssoCode <span class="token operator">=</span> inv<span class="token punctuation">.</span><span class="token function">getController</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getPara</span><span class="token punctuation">(</span><span class="token string">&quot;ssoCode&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        String userId <span class="token operator">=</span> inv<span class="token punctuation">.</span><span class="token function">getController</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getPara</span><span class="token punctuation">(</span><span class="token string">&quot;userId&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">if</span> <span class="token punctuation">(</span>StringUtils<span class="token punctuation">.</span><span class="token function">isBlank</span><span class="token punctuation">(</span>ssoCode<span class="token punctuation">)</span> <span class="token operator">||</span> StringUtils<span class="token punctuation">.</span><span class="token function">isBlank</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">return</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        SSOAuthenticationToken token <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SSOAuthenticationToken</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        token<span class="token punctuation">.</span><span class="token function">setUserId</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span><span class="token punctuation">;</span>
        token<span class="token punctuation">.</span><span class="token function">setSsoCode</span><span class="token punctuation">(</span>ssoCode<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">try</span> <span class="token punctuation">{</span>
            Subject subject <span class="token operator">=</span> SecurityUtils<span class="token punctuation">.</span><span class="token function">getSubject</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            subject<span class="token punctuation">.</span><span class="token function">login</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            log<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span><span class="token function">getMessage</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>实现shiro realm SSOAuthorizingRealm</p><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">SSOAuthorizingRealm</span> <span class="token keyword">extends</span> <span class="token class-name">AuthorizingRealm</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">supports</span><span class="token punctuation">(</span>AuthenticationToken token<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> token <span class="token keyword">instanceof</span> <span class="token class-name">SSOAuthenticationToken</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">protected</span> AuthenticationInfo <span class="token function">doGetAuthenticationInfo</span><span class="token punctuation">(</span>AuthenticationToken token<span class="token punctuation">)</span> <span class="token keyword">throws</span> AuthenticationException <span class="token punctuation">{</span>
        SSOAuthenticationToken ssoToken <span class="token operator">=</span> <span class="token punctuation">(</span>SSOAuthenticationToken<span class="token punctuation">)</span> token<span class="token punctuation">;</span>
        String uid <span class="token operator">=</span> <span class="token punctuation">(</span>String<span class="token punctuation">)</span> ssoToken<span class="token punctuation">.</span><span class="token function">getPrincipal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        String ssoCode <span class="token operator">=</span> token<span class="token punctuation">.</span><span class="token function">getCredentials</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">//判断ssoCode是否为 sso 系统颁发</span>

        <span class="token comment">// 此处判断 uid 是否存在，可以访问等操作</span>
       
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">SimpleAuthenticationInfo</span><span class="token punctuation">(</span>uid<span class="token punctuation">,</span> ssoToken<span class="token punctuation">.</span><span class="token function">getCredentials</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">protected</span> AuthorizationInfo <span class="token function">doGetAuthorizationInfo</span><span class="token punctuation">(</span>PrincipalCollection principals<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// 此处获取 uid 角色权限</span>
        <span class="token keyword">return</span> null<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>实现 shiro 无认证请求重定向到 sso系统，SSOShiroErrorProcess</p><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MyshiroListener</span> <span class="token keyword">implements</span>  <span class="token class-name">JbootShiroInvokeListener</span> <span class="token punctuation">{</span>

        <span class="token annotation punctuation">@Override</span>
        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onInvokeAfter</span><span class="token punctuation">(</span>FixedInvocation inv<span class="token punctuation">,</span> AuthorizeResult result<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>result<span class="token punctuation">.</span><span class="token function">isOk</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                inv<span class="token punctuation">.</span><span class="token function">invoke</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword">return</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
        <span class="token keyword">int</span> errorCode <span class="token operator">=</span> result<span class="token punctuation">.</span><span class="token function">getErrorCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            
        <span class="token keyword">switch</span> <span class="token punctuation">(</span>errorCode<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">case</span> AuthorizeResult<span class="token punctuation">.</span>ERROR_CODE_UNAUTHENTICATED<span class="token operator">:</span>
                <span class="token function">doProcessUnauthenticated</span><span class="token punctuation">(</span>inv<span class="token punctuation">.</span><span class="token function">getController</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword">break</span><span class="token punctuation">;</span>
            <span class="token keyword">case</span> AuthorizeResult<span class="token punctuation">.</span>ERROR_CODE_UNAUTHORIZATION<span class="token operator">:</span>
                <span class="token function">doProcessuUnauthorization</span><span class="token punctuation">(</span>inv<span class="token punctuation">.</span><span class="token function">getController</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword">break</span><span class="token punctuation">;</span>
            <span class="token keyword">default</span><span class="token operator">:</span>
                inv<span class="token punctuation">.</span><span class="token function">getController</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">renderError</span><span class="token punctuation">(</span><span class="token number">404</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>


    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">doProcessUnauthenticated</span><span class="token punctuation">(</span>Controller controller<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        UpmsConfig upmsConfig <span class="token operator">=</span> Jboot<span class="token punctuation">.</span><span class="token function">config</span><span class="token punctuation">(</span>UpmsConfig<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        StringBuilder ssoServerUrl <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StringBuilder</span><span class="token punctuation">(</span>upmsConfig<span class="token punctuation">.</span><span class="token function">getServerUrl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        ssoServerUrl<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">&quot;/sso/index&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">&quot;?&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">&quot;appid&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">&quot;=&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>upmsConfig<span class="token punctuation">.</span><span class="token function">getAppId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">&quot;sysid&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">&quot;=&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>upmsConfig<span class="token punctuation">.</span><span class="token function">getSystemId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// 回跳地址</span>
        StringBuffer backurl <span class="token operator">=</span> controller<span class="token punctuation">.</span><span class="token function">getRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getRequestURL</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        String queryString <span class="token operator">=</span> controller<span class="token punctuation">.</span><span class="token function">getRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getQueryString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>StringUtils<span class="token punctuation">.</span><span class="token function">isNotBlank</span><span class="token punctuation">(</span>queryString<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            backurl<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">&quot;?&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>queryString<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        ssoServerUrl<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">&quot;&amp;&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">&quot;backurl&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">&quot;=&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>StringUtils<span class="token punctuation">.</span><span class="token function">urlEncode</span><span class="token punctuation">(</span>backurl<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        controller<span class="token punctuation">.</span><span class="token function">redirect</span><span class="token punctuation">(</span>ssoServerUrl<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">doProcessuUnauthorization</span><span class="token punctuation">(</span>Controller controller<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        controller<span class="token punctuation">.</span><span class="token function">renderError</span><span class="token punctuation">(</span><span class="token number">403</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>shiro.ini中配置</p><pre class="language-xml"><code>[main]

#cache Manager
shiroCacheManager = io.jboot.component.shiro.cache.JbootShiroCacheManager
securityManager.cacheManager = $shiroCacheManager

#realm
dbRealm=xxx.SSOAuthorizingRealm
dbRealm.authorizationCacheName=shiro-authorizationCache

securityManager.realm=$dbRealm

#session 基于缓存sessionDao，如果缓存已经实现共享，那么session也同样实现共享
sessionDAO=xxx.SessionDAO
sessionDAO.activeSessionsCacheName=shiro-active-session

#设置sessionCookie
sessionIdCookie=org.apache.shiro.web.servlet.SimpleCookie
sessionIdCookie.name=ssotestaid
#sessionIdCookie.domain=demo.com
#sessionIdCookie.path=
#cookie最大有效期，单位秒，默认30天
sessionIdCookie.maxAge=1800
sessionIdCookie.httpOnly=true

#设置session会话管理
sessionManager=org.apache.shiro.web.session.mgt.DefaultWebSessionManager
sessionManager.sessionDAO=$sessionDAO
sessionManager.sessionIdCookie=$sessionIdCookie
sessionManager.sessionIdCookieEnabled=true
sessionManager.sessionIdUrlRewritingEnabled=false
securityManager.sessionManager=$sessionManager
#session过期时间，单位毫秒，默认两天
securityManager.sessionManager.globalSessionTimeout=1800000

</code></pre><h4 id="sso服务端配置"><a href="#sso服务端配置" aria-hidden="true" class="header-anchor">#</a> SSO服务端配置</h4><p>SSO服务端，主要包括登录认证、全局code认证、退出等操作。</p><pre class="language-java"><code><span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/sso&quot;</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@EnableCORS</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">SSOController</span> <span class="token keyword">extends</span> <span class="token class-name">BaseController</span> <span class="token punctuation">{</span>

    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">index</span><span class="token punctuation">(</span>String appid<span class="token punctuation">,</span> String backurl<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// 判断 appid 是否正确，backurl 是否正确</span>

        <span class="token function">redirect</span><span class="token punctuation">(</span><span class="token string">&quot;/sso/login?backurl=&quot;</span> <span class="token operator">+</span> StringUtils<span class="token punctuation">.</span><span class="token function">urlEncode</span><span class="token punctuation">(</span>backurl<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Before</span><span class="token punctuation">(</span>GET<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">login</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        Subject subject <span class="token operator">=</span> SecurityUtils<span class="token punctuation">.</span><span class="token function">getSubject</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        String backurl <span class="token operator">=</span> <span class="token function">getPara</span><span class="token punctuation">(</span><span class="token string">&quot;backurl&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">if</span> <span class="token punctuation">(</span>subject<span class="token punctuation">.</span><span class="token function">isAuthenticated</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            String loginName <span class="token operator">=</span> <span class="token punctuation">(</span>String<span class="token punctuation">)</span> subject<span class="token punctuation">.</span><span class="token function">getPrincipal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

            <span class="token comment">// 判断用户id</span>

            String code <span class="token operator">=</span> <span class="token punctuation">(</span>String<span class="token punctuation">)</span> subject<span class="token punctuation">.</span><span class="token function">getSession</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

            <span class="token keyword">if</span> <span class="token punctuation">(</span>StringUtils<span class="token punctuation">.</span><span class="token function">isBlank</span><span class="token punctuation">(</span>backurl<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                <span class="token function">renderJson</span><span class="token punctuation">(</span>JsonResult<span class="token punctuation">.</span><span class="token function">buildSuccess</span><span class="token punctuation">(</span>code<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span>backurl<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span><span class="token string">&quot;?&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                    backurl <span class="token operator">+=</span> <span class="token string">&quot;&amp;ssoCode=&quot;</span> <span class="token operator">+</span> code <span class="token operator">+</span> <span class="token string">&quot;&amp;userId=&quot;</span> <span class="token operator">+</span> upmsUser<span class="token punctuation">.</span><span class="token function">getId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
                    backurl <span class="token operator">+=</span> <span class="token string">&quot;?ssoCode=&quot;</span> <span class="token operator">+</span> code <span class="token operator">+</span> <span class="token string">&quot;&amp;userId=&quot;</span> <span class="token operator">+</span> upmsUser<span class="token punctuation">.</span><span class="token function">getId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>

            <span class="token function">redirect</span><span class="token punctuation">(</span>backurl<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
            <span class="token function">setAttr</span><span class="token punctuation">(</span><span class="token string">&quot;backurl&quot;</span><span class="token punctuation">,</span> backurl<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token function">render</span><span class="token punctuation">(</span><span class="token string">&quot;login.html&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Before</span><span class="token punctuation">(</span>POST<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
    <span class="token annotation punctuation">@EmptyValidate</span><span class="token punctuation">(</span>value <span class="token operator">=</span> <span class="token punctuation">{</span>
            <span class="token annotation punctuation">@Form</span><span class="token punctuation">(</span>name <span class="token operator">=</span> <span class="token string">&quot;loginName&quot;</span><span class="token punctuation">,</span> message <span class="token operator">=</span> <span class="token string">&quot;用户名不能为空&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
            <span class="token annotation punctuation">@Form</span><span class="token punctuation">(</span>name <span class="token operator">=</span> <span class="token string">&quot;password&quot;</span><span class="token punctuation">,</span> message <span class="token operator">=</span> <span class="token string">&quot;密码不能为空&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span> renderType <span class="token operator">=</span> ValidateRenderType<span class="token punctuation">.</span>JSON<span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">postLogin</span><span class="token punctuation">(</span>String loginName<span class="token punctuation">,</span> String password<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        Subject subject <span class="token operator">=</span> SecurityUtils<span class="token punctuation">.</span><span class="token function">getSubject</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        String backUrl <span class="token operator">=</span> <span class="token function">getPara</span><span class="token punctuation">(</span><span class="token string">&quot;backUrl&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        Ret ret <span class="token operator">=</span> JsonResult<span class="token punctuation">.</span><span class="token function">buildSuccess</span><span class="token punctuation">(</span><span class="token string">&quot;登录成功&quot;</span><span class="token punctuation">,</span> backUrl<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>subject<span class="token punctuation">.</span><span class="token function">isAuthenticated</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            UsernamePasswordToken usernamePasswordToken <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">UsernamePasswordToken</span><span class="token punctuation">(</span>loginName<span class="token punctuation">,</span> password<span class="token punctuation">)</span><span class="token punctuation">;</span>
            subject<span class="token punctuation">.</span><span class="token function">login</span><span class="token punctuation">(</span>usernamePasswordToken<span class="token punctuation">)</span><span class="token punctuation">;</span>

            <span class="token comment">// 获取用户 id</span>
            
            Session session <span class="token operator">=</span> subject<span class="token punctuation">.</span><span class="token function">getSession</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            String code <span class="token operator">=</span> session<span class="token punctuation">.</span><span class="token function">getId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

            String backurl <span class="token operator">=</span> <span class="token function">getPara</span><span class="token punctuation">(</span><span class="token string">&quot;backurl&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>StringUtils<span class="token punctuation">.</span><span class="token function">isBlank</span><span class="token punctuation">(</span>backurl<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                <span class="token function">renderJson</span><span class="token punctuation">(</span>JsonResult<span class="token punctuation">.</span><span class="token function">buildSuccess</span><span class="token punctuation">(</span>code<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span>backurl<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span><span class="token string">&quot;?&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                    backurl <span class="token operator">+=</span> <span class="token string">&quot;&amp;ssoCode=&quot;</span> <span class="token operator">+</span> code <span class="token operator">+</span> <span class="token string">&quot;&amp;userId=&quot;</span> <span class="token operator">+</span> upmsUser<span class="token punctuation">.</span><span class="token function">getId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
                    backurl <span class="token operator">+=</span> <span class="token string">&quot;?ssoCode=&quot;</span> <span class="token operator">+</span> code <span class="token operator">+</span> <span class="token string">&quot;&amp;userId=&quot;</span> <span class="token operator">+</span> upmsUser<span class="token punctuation">.</span><span class="token function">getId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>

            <span class="token function">redirect</span><span class="token punctuation">(</span>backurl<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span><span class="token punctuation">;</span>

        <span class="token punctuation">}</span>

        <span class="token function">renderJson</span><span class="token punctuation">(</span>ret<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Before</span><span class="token punctuation">(</span>POST<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
    <span class="token annotation punctuation">@EmptyValidate</span><span class="token punctuation">(</span>value <span class="token operator">=</span> <span class="token punctuation">{</span>
            <span class="token annotation punctuation">@Form</span><span class="token punctuation">(</span>name <span class="token operator">=</span> <span class="token string">&quot;code&quot;</span><span class="token punctuation">,</span> message <span class="token operator">=</span> <span class="token string">&quot;参数错误&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span> renderType <span class="token operator">=</span> ValidateRenderType<span class="token punctuation">.</span>JSON<span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">code</span><span class="token punctuation">(</span>String code<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        Object codeCache <span class="token operator">=</span> null<span class="token punctuation">;</span> <span class="token comment">// 获取缓存全局code</span>

        <span class="token keyword">if</span> <span class="token punctuation">(</span>codeCache <span class="token operator">==</span> null<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token function">renderJson</span><span class="token punctuation">(</span>JsonResult<span class="token punctuation">.</span><span class="token function">buildError</span><span class="token punctuation">(</span><span class="token string">&quot;invalid&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
            <span class="token function">renderJson</span><span class="token punctuation">(</span>JsonResult<span class="token punctuation">.</span><span class="token function">buildSuccess</span><span class="token punctuation">(</span><span class="token string">&quot;success&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>


    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">logout</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// shiro退出登录</span>
        SecurityUtils<span class="token punctuation">.</span><span class="token function">getSubject</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">logout</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">// 跳回原地址</span>
        String redirectUrl <span class="token operator">=</span> <span class="token function">getRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getHeader</span><span class="token punctuation">(</span><span class="token string">&quot;Referer&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>null <span class="token operator">==</span> redirectUrl<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            redirectUrl <span class="token operator">=</span> <span class="token string">&quot;/&quot;</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token function">redirect</span><span class="token punctuation">(</span>redirectUrl<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><h1 id="orm"><a href="#orm" aria-hidden="true" class="header-anchor">#</a> ORM</h1><h2 id="配置"><a href="#配置" aria-hidden="true" class="header-anchor">#</a> 配置</h2><p>在使用数据库之前，需要给Jboot应用做一些配置，实际上，在任何需要用到数据库的应用中，都需要给应用程序做一些配置，让应用程序知道去哪里读取数据。</p><p>由于Jboot的数据库读取是依赖于JFinal，所以实际上只要是JFinal支持的数据库类型，Jboot都会支持，比如常用的数据库类型有：</p><ul><li>Mysql</li><li>Oracle</li><li>SqlServer</li><li>postgresql</li><li>sqlite</li><li>其他标准的数据库</li></ul><p>在Jboot应用连接数据库之前，我们需要在resources目录下创建一个jboot.properties配置文件，并在jboot.properties编写内容如下：</p><pre class="language-xml"><code>jboot.datasource.type=mysql
jboot.datasource.url=jdbc:mysql://127.0.0.1:3306/jbootdemo
jboot.datasource.user=root
jboot.datasource.password=your_password
</code></pre><p>其中：</p><ul><li>jboot.datasource.type 是配置数据库类型</li><li>jboot.datasource.url 是数据库请求URL地址</li><li>jboot.datasource.user 是数据库需要的账号</li><li>jboot.datasource.password 是数据库需要的密码</li></ul><h3 id="高级配置"><a href="#高级配置" aria-hidden="true" class="header-anchor">#</a> 高级配置</h3><p>除了 <code>type</code>，<code>url</code>，<code>user</code>，<code>password</code>四个配置以外，jbootdatasource 还支持以下配置：</p><ul><li>jboot.datasource.name 数据源的名称</li><li>jboot.datasource.driverClassName 驱动类名</li><li>jboot.datasource.connectionInitSql 连接初始化Sql</li><li>jboot.datasource.poolName 线程池名称</li><li>jboot.datasource.cachePrepStmt 缓存启用</li><li>jboot.datasource.prepStmtCacheSize 缓存大小</li><li>jboot.datasource.prepStmtCacheSqlLimit 缓存限制</li><li>jboot.datasource.maximumPoolSize 线程池大小</li><li>jboot.datasource.sqlTemplatePath sql文件路径</li><li>jboot.datasource.sqlTemplate sql文件，多个用英文逗号隔开</li><li>jboot.datasource.table 该数据源对应的表名，多个表用英文逗号隔开</li></ul><p>更多的具体使用，特别是name、table等在分库分表章节会讲到。</p><h2 id="model"><a href="#model" aria-hidden="true" class="header-anchor">#</a> Model</h2><p>model是MVC设计模式中的M，但同时每个model也会对应一个数据库表，它充当 MVC 模式中的 Model 部分。以下是Model 定义示例代码：</p><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">JbootModel</span><span class="token generics function"><span class="token punctuation">&lt;</span>User<span class="token punctuation">&gt;</span></span> <span class="token punctuation">{</span>
	<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">final</span> User dao <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">User</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">dao</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>以上代码中的 User 通过继承 Model，便立即拥有的众多方便的操作数据库的方法。在 User中声明的 dao 静态对象是为了方便查询操作而定义的，该对象并不是必须的。同时，model无需定义 getter、setter 方法，无需 XML 配置，极大降低了代码量。</p><p>以下是model常见的用法：</p><pre class="language-java"><code><span class="token comment">// 创建name属性为James,age属性为25的User对象并添加到数据库</span>
<span class="token keyword">new</span> <span class="token class-name">User</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">&quot;name&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;James&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">&quot;age&quot;</span><span class="token punctuation">,</span> <span class="token number">25</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 删除id值为25的User</span>
User<span class="token punctuation">.</span>dao<span class="token punctuation">.</span><span class="token function">deleteById</span><span class="token punctuation">(</span><span class="token number">25</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 查询id值为25的User将其name属性改为James并更新到数据库</span>
User<span class="token punctuation">.</span>dao<span class="token punctuation">.</span><span class="token function">findById</span><span class="token punctuation">(</span><span class="token number">25</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">&quot;name&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;James&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 查询id值为25的user, 且仅仅取name与age两个字段的值</span>
User user <span class="token operator">=</span> User<span class="token punctuation">.</span>dao<span class="token punctuation">.</span><span class="token function">findByIdLoadColumns</span><span class="token punctuation">(</span><span class="token number">25</span><span class="token punctuation">,</span> <span class="token string">&quot;name, age&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 获取user的name属性</span>
String userName <span class="token operator">=</span> user<span class="token punctuation">.</span><span class="token function">getStr</span><span class="token punctuation">(</span><span class="token string">&quot;name&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 获取user的age属性</span>
Integer userAge <span class="token operator">=</span> user<span class="token punctuation">.</span><span class="token function">getInt</span><span class="token punctuation">(</span><span class="token string">&quot;age&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 查询所有年龄大于18岁的user</span>
List<span class="token generics function"><span class="token punctuation">&lt;</span>User<span class="token punctuation">&gt;</span></span> users <span class="token operator">=</span> User<span class="token punctuation">.</span>dao<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token string">&quot;select * from user where age&gt;18&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 分页查询年龄大于18的user,当前页号为1,每页10个user</span>
Page<span class="token generics function"><span class="token punctuation">&lt;</span>User<span class="token punctuation">&gt;</span></span> userPage <span class="token operator">=</span> User<span class="token punctuation">.</span>dao<span class="token punctuation">.</span><span class="token function">paginate</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">,</span> <span class="token string">&quot;select *&quot;</span><span class="token punctuation">,</span> &quot;from user
where age <span class="token operator">&gt;</span> <span class="token operator">?</span>&quot;<span class="token punctuation">,</span> <span class="token number">18</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>**注意：**User 中定义的 public static final User dao 对象是全局共享的，<strong>只能</strong> 用于数据库查询，<strong>不能</strong> 用于数据承载对象。数据承载需要使用 new User().set(…)来实现。</p><h3 id="table注解"><a href="#table注解" aria-hidden="true" class="header-anchor">#</a> @Table注解</h3><p>@Table注解是给Model使用的，表示让Model映射到哪个数据库表，使用代码如下：</p><pre class="language-java"><code><span class="token annotation punctuation">@Table</span><span class="token punctuation">(</span>tableName <span class="token operator">=</span> <span class="token string">&quot;user&quot;</span><span class="token punctuation">,</span> primaryKey <span class="token operator">=</span> <span class="token string">&quot;id&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">JbootModel</span> <span class="token generics function"><span class="token punctuation">&lt;</span>Company<span class="token punctuation">&gt;</span></span> <span class="token punctuation">{</span>
	
<span class="token punctuation">}</span>
</code></pre><p>值得注意的是：</p><p>在Jboot应用中，我们几乎感受不到@Table这个注解的存在，因为这部分完全是代码生成器生成的，关于代码生成器，请查看 代码生成器章节。</p><h2 id="db-record-模式"><a href="#db-record-模式" aria-hidden="true" class="header-anchor">#</a> Db + Record 模式</h2><p>Db 类及其配套的 Record 类，提供了在 Model 类之外更为丰富的数据库操作功能。使用Db 与 Record 类时，无需对数据库表进行映射，Record 相当于一个通用的 Model。以下为 Db +Record 模式的一些常见用法：</p><pre class="language-java"><code><span class="token comment">// 创建name属性为James,age属性为25的record对象并添加到数据库</span>
Record user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Record</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">&quot;name&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;James&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">&quot;age&quot;</span><span class="token punctuation">,</span> <span class="token number">25</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Db<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span><span class="token string">&quot;user&quot;</span><span class="token punctuation">,</span> user<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 删除id值为25的user表中的记录</span>
Db<span class="token punctuation">.</span><span class="token function">deleteById</span><span class="token punctuation">(</span><span class="token string">&quot;user&quot;</span><span class="token punctuation">,</span> <span class="token number">25</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 查询id值为25的Record将其name属性改为James并更新到数据库</span>
user <span class="token operator">=</span> Db<span class="token punctuation">.</span><span class="token function">findById</span><span class="token punctuation">(</span><span class="token string">&quot;user&quot;</span><span class="token punctuation">,</span> <span class="token number">25</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">&quot;name&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;James&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Db<span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span><span class="token string">&quot;user&quot;</span><span class="token punctuation">,</span> user<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 获取user的name属性</span>
String userName <span class="token operator">=</span> user<span class="token punctuation">.</span><span class="token function">getStr</span><span class="token punctuation">(</span><span class="token string">&quot;name&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 获取user的age属性</span>
Integer userAge <span class="token operator">=</span> user<span class="token punctuation">.</span><span class="token function">getInt</span><span class="token punctuation">(</span><span class="token string">&quot;age&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 查询所有年龄大于18岁的user</span>
Page<span class="token generics function"><span class="token punctuation">&lt;</span>Record<span class="token punctuation">&gt;</span></span> userPage <span class="token operator">=</span> Db<span class="token punctuation">.</span><span class="token function">paginate</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">,</span> <span class="token string">&quot;select *&quot;</span><span class="token punctuation">,</span> &quot;from user where
age <span class="token operator">&gt;</span> <span class="token operator">?</span>&quot;<span class="token punctuation">,</span> <span class="token number">18</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>或者，事务操作：</p><pre class="language-java"><code><span class="token keyword">boolean</span> succeed <span class="token operator">=</span> Db<span class="token punctuation">.</span><span class="token function">tx</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">IAtom</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
		<span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> SQLException <span class="token punctuation">{</span>
		<span class="token keyword">int</span> count <span class="token operator">=</span> Db<span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span>&quot;update account set cash <span class="token operator">=</span> cash <span class="token operator">-</span> <span class="token operator">?</span> where
		id <span class="token operator">=</span> <span class="token operator">?</span>&quot;<span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">123</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">int</span> count2 <span class="token operator">=</span> Db<span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span>&quot;update account set cash <span class="token operator">=</span> cash <span class="token operator">+</span> <span class="token operator">?</span> where
		id <span class="token operator">=</span> <span class="token operator">?</span>&quot;<span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">456</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">return</span> count <span class="token operator">==</span> <span class="token number">1</span> <span class="token operator">&amp;&amp;</span> count2 <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>以上两次数据库更新操作在一个事务中执行，如果执行过程中发生异常或者 run()方法返回 false，则自动回滚事务。</p><h2 id="更多"><a href="#更多" aria-hidden="true" class="header-anchor">#</a> 更多</h2><p>请参考JFinal的文档：http://download.jfinal.com/download/3.2/jfinal-3.2-manual.pdf</p><h2 id="多数据源"><a href="#多数据源" aria-hidden="true" class="header-anchor">#</a> 多数据源</h2><p>在Jboot中，使用多数据源非常简单。</p><p>在以上章节里，我们知道，要连接数据库需要做如下配置：</p><pre class="language-xml"><code>jboot.datasource.type=mysql
jboot.datasource.url=jdbc:mysql://127.0.0.1:3306/jbootdemo
jboot.datasource.user=root
jboot.datasource.password=your_password
</code></pre><p>假设我们再增加两个数据源，只需要在jboot.properties文件在添加如下配置即可：</p><pre class="language-xml"><code>jboot.datasource.a1.type=mysql
jboot.datasource.a1.turl=jdbc:mysql://127.0.0.1:3306/jboot1
jboot.datasource.a1.tuser=root
jboot.datasource.a1.tpassword=your_password

jboot.datasource.a2.type=mysql
jboot.datasource.a2.turl=jdbc:mysql://127.0.0.1:3306/jboot2
jboot.datasource.a2.tuser=root
jboot.datasource.a2.tpassword=your_password
</code></pre><p>这表示，我们又增加了数据源<code>a1</code>和数据源<code>a2</code>，在使用的时候，我们只需要做一下使用：</p><pre class="language-java"><code>Company company <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Company</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
company<span class="token punctuation">.</span><span class="token function">setCid</span><span class="token punctuation">(</span><span class="token string">&quot;1&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
company<span class="token punctuation">.</span><span class="token function">setName</span><span class="token punctuation">(</span><span class="token string">&quot;name&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

company<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">&quot;a1&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p><code>company.use(&quot;a1&quot;).save();</code>表示使用数据源<code>a1</code>进行保存。</p><p><strong>值得注意的是：</strong></p><p>在多数据源应用中，很多时候，我们一个Model只有对应一个数据源，而不是一个Model对应多个数据源。假设Company只有在<code>a1</code>数据源中存在，在其他数据源并不存在，我们需要把<code>a1</code>数据源的配置修改如下：</p><pre class="language-xml"><code>jboot.datasource.a1.type=mysql
jboot.datasource.a1.url=jdbc:mysql://127.0.0.1:3306/jboot1
jboot.datasource.a1.user=root
jboot.datasource.a1.password=your_password
jboot.datasource.a1.table=company

jboot.datasource.a2.type=mysql
jboot.datasource.a2.url=jdbc:mysql://127.0.0.1:3306/jboot2
jboot.datasource.a2.user=root
jboot.datasource.a2.password=your_password
jboot.datasource.a1.table=user,xxx(其他非company表)
</code></pre><p>这样，company在<code>a1</code>数据源中存在，Jboot在初始化的时候，并不会去检查company在其他数据源中是否存在，同时，代码操作company的时候，不再需要use，代码如下：</p><pre class="language-java"><code>Company company <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Company</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
company<span class="token punctuation">.</span><span class="token function">setCid</span><span class="token punctuation">(</span><span class="token string">&quot;1&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
company<span class="token punctuation">.</span><span class="token function">setName</span><span class="token punctuation">(</span><span class="token string">&quot;name&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">//company.use(&quot;a1&quot;).save();</span>
company<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>代码中不再需要 <code>use(&quot;a1&quot;)</code> 指定数据源，因为company只有一个数据源。</p><h2 id="分库和分表"><a href="#分库和分表" aria-hidden="true" class="header-anchor">#</a> 分库和分表</h2><p>在Jboot中，分表是通过sharding-jdbc（ 网址：https://github.com/shardingjdbc/sharding-jdbc） 来实现的，所以，在了解Jboot的分表之前，请先阅读了解sharding-jdbc的配置信息。</p><p>分库分表相关demo: <a href="./src/test/java/sharding">点击这里</a></p><h3 id="分库"><a href="#分库" aria-hidden="true" class="header-anchor">#</a> 分库</h3><p>分库意味你有多个数据库，每个数据库会对应一个数据源。</p><p>例如，我们的应用有三个数据库，分别是 db1,db2,db3，那么需要我们在 jboot.properties 配置文件里配置上三个数据，配置如下：</p><pre class="language-text"><code>jboot.datasource.db1.url = jdbc:mysql://127.0.0.1:3306/db1
jboot.datasource.db1.user = root
jboot.datasource.db1.password = 

jboot.datasource.db2.url = jdbc:mysql://127.0.0.1:3306/db2
jboot.datasource.db2.user = root
jboot.datasource.db2.password = 

jboot.datasource.db3.url = jdbc:mysql://127.0.0.1:3306/db3
jboot.datasource.db3.user = root
jboot.datasource.db3.password = 

</code></pre><p>我们希望在分库的时候，通过Model的主键ID进行hashcode进行取模，决定分库。因此需要编写分库策略，代码如下：</p><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserDatabaseShardingStrategyConfig</span> <span class="token keyword">implements</span> <span class="token class-name">ShardingStrategyConfiguration</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> ShardingStrategy <span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> shardingStrategy<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>


    <span class="token keyword">private</span> ShardingStrategy shardingStrategy <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ShardingStrategy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

        <span class="token annotation punctuation">@Override</span>
        <span class="token keyword">public</span> Collection<span class="token generics function"><span class="token punctuation">&lt;</span>String<span class="token punctuation">&gt;</span></span> <span class="token function">getShardingColumns</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token comment">//根据id进行分库</span>
            <span class="token keyword">return</span> Sets<span class="token punctuation">.</span><span class="token function">newHashSet</span><span class="token punctuation">(</span><span class="token string">&quot;id&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token annotation punctuation">@Override</span>
        <span class="token keyword">public</span> Collection<span class="token generics function"><span class="token punctuation">&lt;</span>String<span class="token punctuation">&gt;</span></span> <span class="token function">doSharding</span><span class="token punctuation">(</span>Collection<span class="token generics function"><span class="token punctuation">&lt;</span>String<span class="token punctuation">&gt;</span></span> availableTargetNames<span class="token punctuation">,</span> Collection<span class="token generics function"><span class="token punctuation">&lt;</span>ShardingValue<span class="token punctuation">&gt;</span></span> shardingValues<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            ListShardingValue shardingValue <span class="token operator">=</span> <span class="token punctuation">(</span>ListShardingValue<span class="token punctuation">)</span> shardingValues<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">findFirst</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

            String dbName <span class="token operator">=</span> <span class="token string">&quot;db&quot;</span> <span class="token operator">+</span> Math<span class="token punctuation">.</span><span class="token function">abs</span><span class="token punctuation">(</span>shardingValue<span class="token punctuation">.</span><span class="token function">getValues</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">iterator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">hashCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">%</span> <span class="token number">3</span><span class="token punctuation">;</span>

            System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">&quot;插入数据到库：&quot;</span> <span class="token operator">+</span> dbName<span class="token punctuation">)</span><span class="token punctuation">;</span>

            <span class="token comment">//返回通过计算得到的表</span>
            <span class="token keyword">return</span> Sets<span class="token punctuation">.</span><span class="token function">newHashSet</span><span class="token punctuation">(</span>dbName<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token punctuation">}</span>
</code></pre><p>编写好分库策略后，需要给Model配置上分库策略：</p><pre class="language-java"><code><span class="token annotation punctuation">@Table</span><span class="token punctuation">(</span>tableName <span class="token operator">=</span> <span class="token string">&quot;tb_user&quot;</span><span class="token punctuation">,</span>
        primaryKey <span class="token operator">=</span> <span class="token string">&quot;id&quot;</span><span class="token punctuation">,</span>
         <span class="token comment">// 具体的表tb_user${0..2} 表示有三张表 tb_user0,tb_user1,tb_user2,</span>
         <span class="token comment">// main 是默认数据源的名称</span>
        actualDataNodes <span class="token operator">=</span> <span class="token string">&quot;main.tb_user${0..2}&quot;</span><span class="token punctuation">,</span>
        <span class="token comment">//分表策略</span>
        databaseShardingStrategyConfig <span class="token operator">=</span> UserDatabaseShardingStrategyConfig<span class="token punctuation">.</span><span class="token keyword">class</span> 
<span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserModel</span> <span class="token keyword">extends</span> <span class="token class-name">JbootModel</span><span class="token generics function"><span class="token punctuation">&lt;</span>UserModel<span class="token punctuation">&gt;</span></span> <span class="token punctuation">{</span>


   <span class="token comment">//geter setter</span>
<span class="token punctuation">}</span>

</code></pre><h3 id="分表"><a href="#分表" aria-hidden="true" class="header-anchor">#</a> 分表</h3><h4 id="demos"><a href="#demos" aria-hidden="true" class="header-anchor">#</a> demos</h4><p>例如：有一个userModel，我们希望能进行分为三张表，通过id的hashcode进行取模，代码如下：</p><pre class="language-java"><code>
<span class="token annotation punctuation">@Table</span><span class="token punctuation">(</span>tableName <span class="token operator">=</span> <span class="token string">&quot;tb_user&quot;</span><span class="token punctuation">,</span>
        primaryKey <span class="token operator">=</span> <span class="token string">&quot;id&quot;</span><span class="token punctuation">,</span>
         <span class="token comment">// 具体的表tb_user${0..2} 表示有三张表 tb_user0,tb_user1,tb_user2,</span>
         <span class="token comment">// main 是默认数据源的名称</span>
        actualDataNodes <span class="token operator">=</span> <span class="token string">&quot;main.tb_user${0..2}&quot;</span><span class="token punctuation">,</span>
        <span class="token comment">//分表策略</span>
        tableShardingStrategyConfig <span class="token operator">=</span> UserTableShardingStrategyConfig<span class="token punctuation">.</span><span class="token keyword">class</span> 
<span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserModel</span> <span class="token keyword">extends</span> <span class="token class-name">JbootModel</span><span class="token generics function"><span class="token punctuation">&lt;</span>UserModel<span class="token punctuation">&gt;</span></span> <span class="token punctuation">{</span>


    <span class="token comment">//geter setter</span>
<span class="token punctuation">}</span>

</code></pre><p>编写UserModel的分表策略  UserTableShardingStrategyConfig，代码如下：</p><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserTableShardingStrategyConfig</span> <span class="token keyword">implements</span> <span class="token class-name">ShardingStrategyConfiguration</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> ShardingStrategy <span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> shardingStrategy<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>


    <span class="token keyword">private</span> ShardingStrategy shardingStrategy <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ShardingStrategy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

        <span class="token annotation punctuation">@Override</span>
        <span class="token keyword">public</span> Collection<span class="token generics function"><span class="token punctuation">&lt;</span>String<span class="token punctuation">&gt;</span></span> <span class="token function">getShardingColumns</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token comment">//根据id进行分表</span>
            <span class="token keyword">return</span> Sets<span class="token punctuation">.</span><span class="token function">newHashSet</span><span class="token punctuation">(</span><span class="token string">&quot;id&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token annotation punctuation">@Override</span>
        <span class="token keyword">public</span> Collection<span class="token generics function"><span class="token punctuation">&lt;</span>String<span class="token punctuation">&gt;</span></span> <span class="token function">doSharding</span><span class="token punctuation">(</span>Collection<span class="token generics function"><span class="token punctuation">&lt;</span>String<span class="token punctuation">&gt;</span></span> availableTargetNames<span class="token punctuation">,</span> Collection<span class="token generics function"><span class="token punctuation">&lt;</span>ShardingValue<span class="token punctuation">&gt;</span></span> shardingValues<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            ListShardingValue shardingValue <span class="token operator">=</span> <span class="token punctuation">(</span>ListShardingValue<span class="token punctuation">)</span> shardingValues<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">findFirst</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

            String tableName <span class="token operator">=</span> <span class="token string">&quot;tb_user&quot;</span> <span class="token operator">+</span> Math<span class="token punctuation">.</span><span class="token function">abs</span><span class="token punctuation">(</span>shardingValue<span class="token punctuation">.</span><span class="token function">getValues</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">iterator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">hashCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">%</span> <span class="token number">3</span><span class="token punctuation">;</span>

            System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">&quot;插入数据到表：&quot;</span> <span class="token operator">+</span> tableName<span class="token punctuation">)</span><span class="token punctuation">;</span>

            <span class="token comment">//返回通过计算得到的表</span>
            <span class="token keyword">return</span> Sets<span class="token punctuation">.</span><span class="token function">newHashSet</span><span class="token punctuation">(</span>tableName<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token punctuation">}</span>
</code></pre><p>编写配置文件：</p><pre class="language-text"><code>jboot.datasource.type=mysql
jboot.datasource.url=jdbc:mysql://127.0.0.1:3306/jbootsharding
jboot.datasource.user=root
jboot.datasource.password=
jboot.datasource.shardingEnable=true
</code></pre><p>进行UserModel保存到数据库</p><pre class="language-java"><code><span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/sharding&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ShardingController</span> <span class="token keyword">extends</span> <span class="token class-name">JbootController</span> <span class="token punctuation">{</span>

    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">index</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        UserModel user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">UserModel</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        user<span class="token punctuation">.</span><span class="token function">setId</span><span class="token punctuation">(</span>StringUtils<span class="token punctuation">.</span><span class="token function">uuid</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        user<span class="token punctuation">.</span><span class="token function">setName</span><span class="token punctuation">(</span><span class="token string">&quot;Michael yang&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        user<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token function">renderText</span><span class="token punctuation">(</span><span class="token string">&quot;插入数据成功，请查看数据库...&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        Jboot<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>具体demo请参考：</p><p>https://gitee.com/fuhai/jboot/tree/master/src/test/java/sharding</p><h1 id="aop"><a href="#aop" aria-hidden="true" class="header-anchor">#</a> AOP</h1><h2 id="google-guice"><a href="#google-guice" aria-hidden="true" class="header-anchor">#</a> Google Guice</h2><p>Jboot 的AOP功能，是使用了Google的Guice框架来完成的，通过AOP，我们可以轻易的在微服务体系中监控api的调用，轻易的使用@Cacheable，@CachePut，@CacheEvict等注解完成对代码的配置。</p><h2 id="inject-和-bean"><a href="#inject-和-bean" aria-hidden="true" class="header-anchor">#</a> @Inject 和 @Bean</h2><p>和Spring一样，Jboot是通过注解 <code>@Inject</code> 来对变量进行赋值注入的，例如：</p><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">AopDemo</span> <span class="token keyword">extends</span> <span class="token class-name">JbootController</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Inject</span>
    CategoryService service<span class="token punctuation">;</span>

    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">index</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">renderHtml</span><span class="token punctuation">(</span><span class="token string">&quot;service:&quot;</span> <span class="token operator">+</span> service<span class="token punctuation">.</span><span class="token function">hello</span><span class="token punctuation">(</span><span class="token string">&quot;&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
      
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        Jboot<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>但是，必须强调的是：<code>CategoryService</code>接口能够被注入，其实必须有实现类，同时实现类必须通过 <code>@Bean</code> 进行配置，例如：</p><p>接口代码：</p><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">CategoryService</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> String <span class="token function">hello</span><span class="token punctuation">(</span>String text<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>实现类代码：</p><pre class="language-java"><code><span class="token annotation punctuation">@Bean</span> <span class="token comment">//必须通过 @Bean 进行配置，让CategoryServiceImpl处于自动暴露状态</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">CategoryServiceImpl</span> <span class="token keyword">implements</span> <span class="token class-name">CategoryService</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> String <span class="token function">hello</span><span class="token punctuation">(</span>String text<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token string">&quot;CategoryServiceImpl say hello &quot;</span> <span class="token operator">+</span> text<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

<span class="token punctuation">}</span>
</code></pre><p>但是，当<code>@Inject</code>注入的不是一个接口类，而是一个普通类，那么无需 <code>@Bean</code> 的配合。例如：</p><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">AopDemo</span> <span class="token keyword">extends</span> <span class="token class-name">JbootController</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Inject</span>
    MyServiceImpl myService<span class="token punctuation">;</span>

    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">index</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">renderHtml</span><span class="token punctuation">(</span><span class="token string">&quot;service:&quot;</span> <span class="token operator">+</span> myService<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
      
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        Jboot<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>在以上代码中，由于 <code>MyServiceImpl</code> 不是已经接口，而是一个类，此时无需在 <code>MyServiceImpl</code> 这个类上配置
<code>@Bean</code> 注解。</p><p>当一个接口有多个实现类的时候，可以通过配合<code>@Named</code>配合进行注入，例如：</p><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">AopDemo</span> <span class="token keyword">extends</span> <span class="token class-name">JbootController</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Inject</span>
    CategoryService service<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Inject</span>
    <span class="token annotation punctuation">@Named</span><span class="token punctuation">(</span><span class="token string">&quot;myCategory&quot;</span><span class="token punctuation">)</span> <span class="token comment">//通过@Named指定使用哪个实现类</span>
    CategoryService nameservice<span class="token punctuation">;</span>

    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">index</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">renderHtml</span><span class="token punctuation">(</span><span class="token string">&quot;service:&quot;</span> <span class="token operator">+</span> service<span class="token punctuation">.</span><span class="token function">hello</span><span class="token punctuation">(</span><span class="token string">&quot;&quot;</span><span class="token punctuation">)</span> 
        <span class="token operator">+</span> <span class="token string">&quot;&lt;br /&gt; nameservice:&quot;</span> <span class="token operator">+</span> nameservice<span class="token punctuation">.</span><span class="token function">hello</span><span class="token punctuation">(</span><span class="token string">&quot;&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
      
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        Jboot<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>以下是实现类的代码：</p><pre class="language-java"><code><span class="token annotation punctuation">@Bean</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">CategoryServiceImpl</span> <span class="token keyword">implements</span> <span class="token class-name">CategoryService</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> String <span class="token function">hello</span><span class="token punctuation">(</span>String text<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token string">&quot;CategoryServiceImpl say hello &quot;</span> <span class="token operator">+</span> text<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><pre class="language-java"><code><span class="token annotation punctuation">@Bean</span><span class="token punctuation">(</span>name <span class="token operator">=</span> <span class="token string">&quot;myCategory&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">NamedCategoryServiceImpl</span> <span class="token keyword">implements</span> <span class="token class-name">CategoryService</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Override</span>
    <span class="token keyword">public</span> String <span class="token function">hello</span><span class="token punctuation">(</span>String text<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token string">&quot;NamedCategoryServiceImpl say hello &quot;</span> <span class="token operator">+</span> text<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>两个类都实现了<code>CategoryService</code>接口，不同的是 <code>NamedCategoryServiceImpl</code> 实现类在配置 <code>@Bean</code> 的时候传了参数 <code>name = &quot;myCategory&quot;</code>，这样，注入的时候就可以配合 <code>@Named</code> 进行对实现类的选择。</p><h2 id="rpcservice"><a href="#rpcservice" aria-hidden="true" class="header-anchor">#</a> @RpcService</h2><p>通过以上 <code>@Inject</code> 和 <code>@Bean</code> 的配合，我们很方便的在项目中自由的对代码进行注入，但是，如果注入的是一个RPC的服务，那么需要通过 <code>@RpcService</code> 进行注入。更多关于RPC部分，请查看RPC章节。</p><h1 id="rpc远程调用"><a href="#rpc远程调用" aria-hidden="true" class="header-anchor">#</a> RPC远程调用</h1><p>在Jboot中，RPC远程调用是通过新浪的motan、或阿里的dubbo来完成的。计划会支持 grpc和thrift等。</p><h3 id="使用步骤："><a href="#使用步骤：" aria-hidden="true" class="header-anchor">#</a> 使用步骤：</h3><h4 id="第一步：配置jboot-properties文件，内容如下："><a href="#第一步：配置jboot-properties文件，内容如下：" aria-hidden="true" class="header-anchor">#</a> 第一步：配置Jboot.properties文件，内容如下：</h4><pre class="language-java"><code>#默认类型为 motan <span class="token punctuation">(</span>支持<span class="token operator">:</span>dubbo<span class="token punctuation">,</span>计划支持 grpc 和 thrift<span class="token punctuation">)</span>
jboot<span class="token punctuation">.</span>rpc<span class="token punctuation">.</span>type <span class="token operator">=</span> motan
#发现服务类型为 consul ，支持zookeeper。
jboot<span class="token punctuation">.</span>rpc<span class="token punctuation">.</span>registryType <span class="token operator">=</span> consul
jboot<span class="token punctuation">.</span>rpc<span class="token punctuation">.</span>registryAddress <span class="token operator">=</span> <span class="token number">127.0</span><span class="token number">.0</span><span class="token number">.1</span><span class="token operator">:</span><span class="token number">8500</span>
</code></pre><h4 id="第二步：定义接口"><a href="#第二步：定义接口" aria-hidden="true" class="header-anchor">#</a> 第二步：定义接口</h4><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">HelloService</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> String <span class="token function">hello</span><span class="token punctuation">(</span>String name<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><h4 id="第三步：通过-jbootrpcservice注解暴露服务到注册中心"><a href="#第三步：通过-jbootrpcservice注解暴露服务到注册中心" aria-hidden="true" class="header-anchor">#</a> 第三步：通过@JbootrpcService注解暴露服务到注册中心</h4><pre class="language-java"><code><span class="token annotation punctuation">@JbootrpcService</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">myHelloServiceImpl</span>  <span class="token keyword">implements</span> <span class="token class-name">HelloService</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> String <span class="token function">hello</span><span class="token punctuation">(</span>String name<span class="token punctuation">)</span><span class="token punctuation">{</span>
         System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">&quot;hello&quot;</span> <span class="token operator">+</span> name<span class="token punctuation">)</span><span class="token punctuation">;</span>
         <span class="token keyword">return</span> <span class="token string">&quot;hello ok&quot;</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><h4 id="第四步：客户调用"><a href="#第四步：客户调用" aria-hidden="true" class="header-anchor">#</a> 第四步：客户调用</h4><pre class="language-java"><code> HelloService service <span class="token operator">=</span> Jboot<span class="token punctuation">.</span><span class="token function">me</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">service</span><span class="token punctuation">(</span>HelloService<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 service<span class="token punctuation">.</span><span class="token function">hello</span><span class="token punctuation">(</span><span class="token string">&quot;michael&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>如果是在Controller中，也可以通过 @JbootrpcService 注解来获取服务，代码如下：</p><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MyController</span> <span class="token keyword">extends</span> <span class="token class-name">JbootController</span><span class="token punctuation">{</span>
    
    <span class="token annotation punctuation">@JbootrpcService</span>
    HelloService service <span class="token punctuation">;</span>
    
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">index</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        String text <span class="token operator">=</span> service<span class="token punctuation">.</span><span class="token function">hello</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">renderText</span><span class="token punctuation">(</span>text<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    
<span class="token punctuation">}</span>
</code></pre><h3 id="配置中心"><a href="#配置中心" aria-hidden="true" class="header-anchor">#</a> 配置中心</h3><h5 id="下载consul"><a href="#下载consul" aria-hidden="true" class="header-anchor">#</a> 下载consul</h5><p>https://www.consul.io</p><h5 id="启动consul"><a href="#启动consul" aria-hidden="true" class="header-anchor">#</a> 启动consul</h5><pre class="language-java"><code>consul agent <span class="token operator">-</span>dev
</code></pre><p>允许其他机器访问consul:</p><pre class="language-java"><code>consul agent <span class="token operator">-</span>dev <span class="token operator">-</span>client<span class="token operator">=</span>本机局域网IP
</code></pre><h4 id="zookeeper"><a href="#zookeeper" aria-hidden="true" class="header-anchor">#</a> zookeeper</h4><h5 id="下载zookeeper"><a href="#下载zookeeper" aria-hidden="true" class="header-anchor">#</a> 下载zookeeper</h5><p>http://zookeeper.apache.org/releases.html</p><h5 id="启动zookeeper"><a href="#启动zookeeper" aria-hidden="true" class="header-anchor">#</a> 启动zookeeper</h5><p>下载zookeeper后，进入zookeeper目录下，找到 conf/zoo_example.cfg，重命名为 zoo.cfg。</p><p>zoo.cfg 内容如下：</p><pre class="language-text"><code>tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
</code></pre><p>在终端模式下，进入 zookeeper的更目录，执行：</p><pre class="language-java"><code>bin<span class="token operator">/</span>zkServer<span class="token punctuation">.</span>sh start
</code></pre><p>关于zookeeper更多的内容，请查看 http://zookeeper.apache.org 和 http://zookeeper.apache.org/doc/trunk/zookeeperStarted.html</p><h1 id="redis操作"><a href="#redis操作" aria-hidden="true" class="header-anchor">#</a> Redis操作</h1><h2 id="redis简介"><a href="#redis简介" aria-hidden="true" class="header-anchor">#</a> Redis简介</h2><p>Redis 是完全开源免费的，遵守BSD协议，是一个高性能的key-value数据库。</p><p>Redis 与其他 key - value 缓存产品有以下三个特点：</p><ul><li>Redis支持数据的持久化，可以将内存中的数据保存在磁盘中，重启的时候可以再次加载进行使用。</li><li>Redis不仅仅支持简单的key-value类型的数据，同时还提供list，set，zset，hash等数据结构的存储。</li><li>Redis支持数据的备份，即master-slave模式的数据备份。</li></ul><p>Redis 优势:</p><ul><li>性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。</li><li>丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。</li><li>原子 – Redis的所有操作都是原子性的，意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务，即原子性，通过MULTI和EXEC指令包起来。</li><li>丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。</li></ul><h2 id="redis的使用"><a href="#redis的使用" aria-hidden="true" class="header-anchor">#</a> Redis的使用</h2><p>在使用Reids之前，先进行Redis配置，配置内容如下：</p><pre class="language-java"><code>jboot<span class="token punctuation">.</span>redis<span class="token punctuation">.</span>host<span class="token operator">=</span><span class="token number">127.0</span><span class="token number">.0</span><span class="token number">.1</span>
jboot<span class="token punctuation">.</span>redis<span class="token punctuation">.</span>password<span class="token operator">=</span>xxxx
</code></pre><p>配置后，就可以通过如下代码获取 JbootRedis 对redis进行操作：</p><pre class="language-java"><code>JbootRedis redis <span class="token operator">=</span> Jboot<span class="token punctuation">.</span><span class="token function">me</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getReids</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
redis<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">&quot;key1&quot;</span><span class="token punctuation">,</span><span class="token string">&quot;value1&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

String value <span class="token operator">=</span> redis<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">&quot;key1&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 输出 value1</span>
</code></pre><h2 id="redis操作系列方法"><a href="#redis操作系列方法" aria-hidden="true" class="header-anchor">#</a> Redis操作系列方法</h2><table><thead><tr><th>指令（方法）</th><th>描述</th></tr></thead><tbody><tr><td>set(Object key, Object value);</td><td>存放 key value 对到 redis，对于某个原本带有生存时间（TTL）的键来说， 当 SET 命令成功在这个键上执行时， 这个键原有的 TTL 将被清除。如果 key 已经持有其他值， SET 就覆写旧值，无视类型。</td></tr><tr><td>setnx</td><td>当且仅当 key 不存在能成功设置</td></tr><tr><td>setWithoutSerialize</td><td>存放 key value 对到 redis，不对value进行序列化，经常用在设置某些 数字或字符串类型的数据</td></tr><tr><td>setex(Object key, int seconds, Object value)</td><td>存放 key value 对到 redis，并将 key 的生存时间设为 seconds (以秒为单位)</td></tr><tr><td>get</td><td>返回 key 所关联的 value 值</td></tr><tr><td>getWithoutSerialize</td><td>返回 key 所关联的 value 值，不对value近反序列化</td></tr><tr><td>del(Object key)</td><td>删除给定的一个 key</td></tr><tr><td>del(Object... keys)</td><td>删除给定的多个 key</td></tr><tr><td>keys</td><td>查找所有符合给定模式 pattern 的 key，例如：KEYS h?llo 匹配 hello ， hallo 和 hxllo 等</td></tr><tr><td>mset</td><td>同时设置一个或多个 key-value 对，例如：mset(&quot;k1&quot;, &quot;v1&quot;, &quot;k2&quot;, &quot;v2&quot;)</td></tr><tr><td>mget</td><td>返回所有(一个或多个)给定 key 的值</td></tr><tr><td>decr</td><td>将 key 中储存的数字值减一</td></tr><tr><td>decrBy(Object key, long longValue)</td><td>将 key 所储存的值减去减量 value</td></tr><tr><td>incr</td><td>将 key 中储存的数字值增一</td></tr><tr><td>incrBy(Object key, long value)</td><td>将 key 所储存的值加上增量 value</td></tr><tr><td>exists</td><td>检查给定 key 是否存在</td></tr><tr><td>randomKey</td><td>从当前数据库中随机返回(不删除)一个 key</td></tr><tr><td>rename</td><td>将 key 改名为 newkey，当 newkey 已经存在时， RENAME 命令将覆盖旧值</td></tr><tr><td>move</td><td>将当前数据库的 key 移动到给定的数据库 db 当中</td></tr><tr><td>migrate</td><td>将 key 原子性地从当前实例传送到目标实例的指定数据库上</td></tr><tr><td>select</td><td>切换到指定的数据库，数据库索引号 index 用数字值指定，以 0 作为起始索引值</td></tr><tr><td>expire</td><td>为给定 key 设置生存时间，当 key 过期时(生存时间为 0 )，它会被自动删除</td></tr><tr><td>expireAt</td><td>expireAt 的作用和 expire 类似，都用于为 key 设置生存时间。不同在于 expireAt 命令接受的时间参数是 UNIX 时间戳(unix timestamp)</td></tr><tr><td>pexpire</td><td>这个命令和 expire 命令的作用类似，但是它以毫秒为单位设置 key 的生存时间</td></tr><tr><td>pexpireAt</td><td>这个命令和 expireAt 命令类似，但它以毫秒为单位设置 key 的过期 unix 时间戳</td></tr><tr><td>getSet</td><td>将给定 key 的值设为 value ，并返回 key 的旧值(old value)</td></tr><tr><td>persist</td><td>移除给定 key 的生存时间</td></tr><tr><td>type</td><td>返回 key 所储存的值的类型</td></tr><tr><td>ttl</td><td>以秒为单位，返回给定 key 的剩余生存时间</td></tr><tr><td>pttl</td><td>这个命令类似于 TTL 命令，但它以毫秒为单位返回 key 的剩余生存时间</td></tr><tr><td>objectRefcount</td><td>对象被引用的数量</td></tr><tr><td>objectIdletime</td><td>对象没有被访问的空闲时间</td></tr><tr><td>hset(Object key, Object field, Object value)</td><td>将哈希表 key 中的域 field 的值设为 value</td></tr><tr><td>hmset(Object key, Map&lt;Object, Object&gt; hash)</td><td>同时将多个 field-value (域-值)对设置到哈希表 key 中</td></tr><tr><td>hget(Object key, Object field)</td><td>返回哈希表 key 中给定域 field 的值</td></tr><tr><td>hmget(Object key, Object... fields)</td><td>返回哈希表 key 中，一个或多个给定域的值</td></tr><tr><td>hdel</td><td>删除哈希表 key 中的一个或多个指定域，不存在的域将被忽略</td></tr><tr><td>hexists</td><td>查看哈希表 key 中，给定域 field 是否存在</td></tr><tr><td>hgetAll</td><td>返回哈希表 key 中，所有的域和值</td></tr><tr><td>hvals</td><td>返回哈希表 key 中所有域的值</td></tr><tr><td>hkeys</td><td>返回哈希表 key 中的所有域</td></tr><tr><td>hlen</td><td>返回哈希表 key 中域的数量</td></tr><tr><td>hincrBy(Object key, Object field, long value)</td><td>为哈希表 key 中的域 field 的值加上增量 value</td></tr><tr><td>hincrByFloat</td><td>为哈希表 key 中的域 field 加上浮点数增量 value</td></tr><tr><td>lindex</td><td>返回列表 key 中，下标为 index 的元素</td></tr><tr><td>getCounter</td><td>获取记数器的值</td></tr><tr><td>llen</td><td>返回列表 key 的长度</td></tr><tr><td>lpop</td><td>移除并返回列表 key 的头元素</td></tr><tr><td>lpush</td><td>将一个或多个值 value 插入到列表 key 的表头</td></tr><tr><td>lset</td><td>将列表 key 下标为 index 的元素的值设置为 value</td></tr><tr><td>lrem</td><td>根据参数 count 的值，移除列表中与参数 value 相等的元素</td></tr><tr><td>lrange(Object key, long start, long end)</td><td>返回列表 key 中指定区间内的元素，区间以偏移量 start 和 stop 指定</td></tr><tr><td>ltrim</td><td>对一个列表进行修剪(trim)，就是说，让列表只保留指定区间内的元素，不在指定区间之内的元素都将被删除</td></tr><tr><td>rpop</td><td>移除并返回列表 key 的尾元素</td></tr><tr><td>rpoplpush</td><td>命令 rpoplpush 在一个原子时间内，执行以下两个动作：1：将列表中的最后一个元素(尾元素)弹出，并返回给客户端。2：将弹出的元素插入到列表 ，作为列表的的头元素</td></tr><tr><td>rpush</td><td>将一个或多个值 value 插入到列表 key 的表尾(最右边)</td></tr><tr><td>blpop(Object... keys)</td><td>blpop 是列表的阻塞式(blocking)弹出原语</td></tr><tr><td>blpop(Integer timeout, Object... keys)</td><td>blpop 是列表的阻塞式(blocking)弹出原语</td></tr><tr><td>brpop(Object... keys)</td><td>列表的阻塞式(blocking)弹出原语</td></tr><tr><td>brpop(Integer timeout, Object... keys)</td><td>列表的阻塞式(blocking)弹出原语</td></tr><tr><td>ping</td><td>使用客户端向服务器发送一个 PING ，如果服务器运作正常的话，会返回一个 PONG</td></tr><tr><td>sadd</td><td>将一个或多个 member 元素加入到集合 key 当中，已经存在于集合的 member 元素将被忽略</td></tr><tr><td>scard</td><td>返回集合 key 的基数(集合中元素的数量)</td></tr><tr><td>spop</td><td>移除并返回集合中的一个随机元素</td></tr><tr><td>smembers</td><td>返回集合 key 中的所有成员</td></tr><tr><td>sismember</td><td>判断 member 元素是否集合 key 的成员</td></tr><tr><td>sinter</td><td>返回多个集合的交集，多个集合由 keys 指定</td></tr><tr><td>srandmember</td><td>返回集合中的一个随机元素</td></tr><tr><td>srandmember</td><td>返回集合中的 count 个随机元素</td></tr><tr><td>srem</td><td>移除集合 key 中的一个或多个 member 元素，不存在的 member 元素会被忽略</td></tr><tr><td>sunion</td><td>返回多个集合的并集，多个集合由 keys 指定</td></tr><tr><td>sdiff</td><td>返回一个集合的全部成员，该集合是所有给定集合之间的差集</td></tr><tr><td>zadd(Object key, double score, Object member)</td><td>将一个或多个 member 元素及其 score 值加入到有序集 key 当中</td></tr><tr><td>zadd(Object key, Map&lt;Object, Double&gt; scoreMembers)</td><td>同上</td></tr><tr><td>zcard</td><td>返回有序集 key 的基数</td></tr><tr><td>zcount</td><td>返回有序集 key 中， score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员的数量</td></tr><tr><td>zincrby</td><td>为有序集 key 的成员 member 的 score 值加上增量 increment</td></tr><tr><td>zrange</td><td>返回有序集 key 中，指定区间内的成员</td></tr><tr><td>zrevrange</td><td>返回有序集 key 中，指定区间内的成员</td></tr><tr><td>zrangeByScore</td><td>返回有序集 key 中，所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员</td></tr><tr><td>zrank</td><td>返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递增(从小到大)顺序排列</td></tr><tr><td>zrevrank</td><td>返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递减(从大到小)排序</td></tr><tr><td>zrem</td><td>移除有序集 key 中的一个或多个成员，不存在的成员将被忽略</td></tr><tr><td>zscore</td><td>返回有序集 key 中，成员 member 的 score 值</td></tr><tr><td>publish(String channel, String message)</td><td>发布一条消息</td></tr><tr><td>publish(byte[] channel, byte[] message)</td><td>发布一条消息</td></tr><tr><td>subscribe(JedisPubSub listener, final String... channels)</td><td>订阅消息</td></tr><tr><td>subscribe(BinaryJedisPubSub binaryListener, final byte[]... channels)</td><td>订阅消息</td></tr></tbody></table><h2 id="redis扩展"><a href="#redis扩展" aria-hidden="true" class="header-anchor">#</a> Redis扩展</h2><p>JbootRedis 是通过 <code>jedis</code> 或者 <code>JedisCluster</code> 进行操作的，如果想扩展自己的方法。可以直接获取 <code>jedis</code> （或<code>JedisCluster</code>) 对 Redis 进行操作，获取  <code>jedis</code>（或<code>JedisCluster</code>) 的代码如下：</p><pre class="language-java"><code>JbootRedis redis <span class="token operator">=</span> Jboot<span class="token punctuation">.</span><span class="token function">me</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getReids</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">//单机模式下</span>
JbootRedisImpl redisImpl <span class="token operator">=</span> <span class="token punctuation">(</span>JbootRedisImpl<span class="token punctuation">)</span>redis<span class="token punctuation">;</span>
Jedis jedis <span class="token operator">=</span> redisImpl<span class="token punctuation">.</span><span class="token function">getJedis</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">//集群模式下</span>
JbootClusterRedisImpl redisImpl <span class="token operator">=</span> <span class="token punctuation">(</span>JbootClusterRedisImpl<span class="token punctuation">)</span>redis<span class="token punctuation">;</span>
JedisCluster jedis <span class="token operator">=</span> redisImpl<span class="token punctuation">.</span><span class="token function">getJedisCluster</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><h2 id="redis集群"><a href="#redis集群" aria-hidden="true" class="header-anchor">#</a> Redis集群</h2><p>在单机模式下，配置文件如下：</p><pre class="language-java"><code>jboot<span class="token punctuation">.</span>redis<span class="token punctuation">.</span>host<span class="token operator">=</span><span class="token number">127.0</span><span class="token number">.0</span><span class="token number">.1</span>
jboot<span class="token punctuation">.</span>redis<span class="token punctuation">.</span>password<span class="token operator">=</span>xxxx
</code></pre><p>在集群模式下，只需要在 jboot.redis.host 配置为多个主机即可，例如：</p><pre class="language-java"><code>## 多个IP用英文逗号隔开
Jboot<span class="token punctuation">.</span>redis<span class="token punctuation">.</span>host<span class="token operator">=</span><span class="token number">192.168</span><span class="token number">.1</span><span class="token number">.33</span><span class="token punctuation">,</span><span class="token number">192.168</span><span class="token number">.1</span><span class="token number">.34</span>
jboot<span class="token punctuation">.</span>redis<span class="token punctuation">.</span>password<span class="token operator">=</span>xxxx
</code></pre><h1 id="mq消息队列"><a href="#mq消息队列" aria-hidden="true" class="header-anchor">#</a> MQ消息队列</h1><p>Jboot 内置整个了MQ消息队列，使用MQ非常简单</p><h4 id="第一步：配置jboot-properties文件，内容如下：-2"><a href="#第一步：配置jboot-properties文件，内容如下：-2" aria-hidden="true" class="header-anchor">#</a> 第一步：配置jboot.properties文件，内容如下：</h4><pre class="language-java"><code>#默认为redis <span class="token punctuation">(</span>支持<span class="token operator">:</span> redis<span class="token punctuation">,</span>activemq<span class="token punctuation">,</span>rabbitmq<span class="token punctuation">,</span>hornetq<span class="token punctuation">,</span>aliyunmq等 <span class="token punctuation">)</span>
jboot<span class="token punctuation">.</span>mq<span class="token punctuation">.</span>type <span class="token operator">=</span> redis
jboot<span class="token punctuation">.</span>mq<span class="token punctuation">.</span>redis<span class="token punctuation">.</span>host <span class="token operator">=</span> <span class="token number">127.0</span><span class="token number">.0</span><span class="token number">.1</span>
jboot<span class="token punctuation">.</span>mq<span class="token punctuation">.</span>redis<span class="token punctuation">.</span>password <span class="token operator">=</span>
jboot<span class="token punctuation">.</span>mq<span class="token punctuation">.</span>redis<span class="token punctuation">.</span>database <span class="token operator">=</span>
</code></pre><h4 id="第二步：在服务器a中添加一个mq消息监听器"><a href="#第二步：在服务器a中添加一个mq消息监听器" aria-hidden="true" class="header-anchor">#</a> 第二步：在服务器A中添加一个MQ消息监听器</h4><pre class="language-java"><code>Jboot<span class="token punctuation">.</span><span class="token function">me</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getMq</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">addMessageListener</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">JbootmqMessageListener</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token annotation punctuation">@Override</span>
        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onMessage</span><span class="token punctuation">(</span>String channel<span class="token punctuation">,</span> Object obj<span class="token punctuation">)</span> <span class="token punctuation">{</span>
           System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> channel<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><h4 id="第三步：服务器b发送一个消息"><a href="#第三步：服务器b发送一个消息" aria-hidden="true" class="header-anchor">#</a> 第三步：服务器B发送一个消息</h4><pre class="language-java"><code> Jboot<span class="token punctuation">.</span><span class="token function">me</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getMq</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">publish</span><span class="token punctuation">(</span>yourObject<span class="token punctuation">,</span> toChannel<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><h4 id="注意：服务器a和服务器b在jboot-properties上应配置相同的内容。"><a href="#注意：服务器a和服务器b在jboot-properties上应配置相同的内容。" aria-hidden="true" class="header-anchor">#</a> 注意：服务器A和服务器B在jboot.properties上应配置相同的内容。</h4><h2 id="redismq"><a href="#redismq" aria-hidden="true" class="header-anchor">#</a> RedisMQ</h2><h2 id="activemq"><a href="#activemq" aria-hidden="true" class="header-anchor">#</a> ActiveMQ</h2><h1 id="cache缓存"><a href="#cache缓存" aria-hidden="true" class="header-anchor">#</a> Cache缓存</h1><p>Jboot中内置支持了ehcache、redis和 一个基于ehcache、redis研发的二级缓存ehredis，在使用Jboot缓存之前，先配置完成缓存的配置。</p><h3 id="使用步骤"><a href="#使用步骤" aria-hidden="true" class="header-anchor">#</a> 使用步骤</h3><h4 id="第一步：配置jboot-properties文件，内容如下：-3"><a href="#第一步：配置jboot-properties文件，内容如下：-3" aria-hidden="true" class="header-anchor">#</a> 第一步：配置jboot.properties文件，内容如下：</h4><pre class="language-java"><code>#默认类型为ehcache ehcache <span class="token punctuation">(</span>支持<span class="token operator">:</span>ehcache<span class="token punctuation">,</span>redis<span class="token punctuation">,</span>ehredis<span class="token punctuation">)</span>
jboot<span class="token punctuation">.</span>cache<span class="token punctuation">.</span>type <span class="token operator">=</span> redis
jboot<span class="token punctuation">.</span>cache<span class="token punctuation">.</span>redis<span class="token punctuation">.</span>host <span class="token operator">=</span> <span class="token number">127.0</span><span class="token number">.0</span><span class="token number">.1</span>
jboot<span class="token punctuation">.</span>cache<span class="token punctuation">.</span>redis<span class="token punctuation">.</span>password <span class="token operator">=</span>
jboot<span class="token punctuation">.</span>cache<span class="token punctuation">.</span>redis<span class="token punctuation">.</span>database <span class="token operator">=</span>
</code></pre><p>备注：ehredis 是一个基于ehcache和redis实现的二级缓存框架。</p><h4 id="第二步：使用缓存"><a href="#第二步：使用缓存" aria-hidden="true" class="header-anchor">#</a> 第二步：使用缓存</h4><pre class="language-java"><code>Jboot<span class="token punctuation">.</span><span class="token function">me</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getCache</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;cacheName&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;key&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;value&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><h3 id="注意事项"><a href="#注意事项" aria-hidden="true" class="header-anchor">#</a> 注意事项</h3><p>Jboot的分布式session是通过缓存实现的，所以如果要启用Jboot的分布式session，请在缓存中配置类型为redis或者ehredis。</p><h2 id="ehcache"><a href="#ehcache" aria-hidden="true" class="header-anchor">#</a> ehcache</h2><h2 id="redis"><a href="#redis" aria-hidden="true" class="header-anchor">#</a> redis</h2><h2 id="ehredis"><a href="#ehredis" aria-hidden="true" class="header-anchor">#</a> ehredis</h2><h1 id="http客户端"><a href="#http客户端" aria-hidden="true" class="header-anchor">#</a> http客户端</h1><p>Jboot内置了一个轻量级的http客户端，可以通过这个客户端方便的对其他第三方http服务器进行数据请求和下载等功能。</p><h3 id="get请求"><a href="#get请求" aria-hidden="true" class="header-anchor">#</a> Get请求</h3><pre class="language-java"><code><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testHttpGet</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
    String html <span class="token operator">=</span> Jboot<span class="token punctuation">.</span><span class="token function">httpGet</span><span class="token punctuation">(</span><span class="token string">&quot;https://www.baidu.com&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>html<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>或者</p><pre class="language-java"><code><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testHttpPost</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
    Map<span class="token generics function"><span class="token punctuation">&lt;</span>String<span class="token punctuation">,</span> Object<span class="token punctuation">&gt;</span></span> params  <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HashMap</span><span class="token operator">&lt;</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    params<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;key1&quot;</span><span class="token punctuation">,</span><span class="token string">&quot;value1&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    params<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;key2&quot;</span><span class="token punctuation">,</span><span class="token string">&quot;value2&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>


    String html <span class="token operator">=</span> Jboot<span class="token punctuation">.</span><span class="token function">httpGet</span><span class="token punctuation">(</span><span class="token string">&quot;http://www.oschina.net/&quot;</span><span class="token punctuation">,</span>params<span class="token punctuation">)</span><span class="token punctuation">;</span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>html<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><h3 id="post请求"><a href="#post请求" aria-hidden="true" class="header-anchor">#</a> Post请求</h3><pre class="language-java"><code><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testHttpPost</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
    String html <span class="token operator">=</span> Jboot<span class="token punctuation">.</span><span class="token function">httpPost</span><span class="token punctuation">(</span><span class="token string">&quot;http://www.xxx.com&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>html<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>或者</p><pre class="language-java"><code><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testHttpPost</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
    Map<span class="token generics function"><span class="token punctuation">&lt;</span>String<span class="token punctuation">,</span> Object<span class="token punctuation">&gt;</span></span> params  <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HashMap</span><span class="token operator">&lt;</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    params<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;key1&quot;</span><span class="token punctuation">,</span><span class="token string">&quot;value1&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    params<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;key2&quot;</span><span class="token punctuation">,</span><span class="token string">&quot;value2&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>


    String html <span class="token operator">=</span> Jboot<span class="token punctuation">.</span><span class="token function">httpPost</span><span class="token punctuation">(</span><span class="token string">&quot;http://www.oschina.net/&quot;</span><span class="token punctuation">,</span>params<span class="token punctuation">)</span><span class="token punctuation">;</span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>html<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><h3 id="文件上传"><a href="#文件上传" aria-hidden="true" class="header-anchor">#</a> 文件上传</h3><pre class="language-java"><code><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testHttpUploadFile</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
    Map<span class="token generics function"><span class="token punctuation">&lt;</span>String<span class="token punctuation">,</span> Object<span class="token punctuation">&gt;</span></span> params  <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HashMap</span><span class="token operator">&lt;</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    params<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;file1&quot;</span><span class="token punctuation">,</span>file1<span class="token punctuation">)</span><span class="token punctuation">;</span>
    params<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">&quot;file2&quot;</span><span class="token punctuation">,</span>file2<span class="token punctuation">)</span><span class="token punctuation">;</span>


    String html <span class="token operator">=</span> Jboot<span class="token punctuation">.</span><span class="token function">httpPost</span><span class="token punctuation">(</span><span class="token string">&quot;http://www.oschina.net/&quot;</span><span class="token punctuation">,</span>params<span class="token punctuation">)</span><span class="token punctuation">;</span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>html<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>备注：文件上传其实和post提交是一样的，只是params中的参数是文件。</p><h3 id="文件下载"><a href="#文件下载" aria-hidden="true" class="header-anchor">#</a> 文件下载</h3><pre class="language-java"><code><span class="token annotation punctuation">@Test</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testHttpDownload</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

    String url <span class="token operator">=</span> <span class="token string">&quot;http://www.xxx.com/abc.zip&quot;</span><span class="token punctuation">;</span>
    File downloadToFile <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">File</span><span class="token punctuation">(</span><span class="token string">&quot;/xxx/abc.zip&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    JbootHttpRequest request <span class="token operator">=</span> JbootHttpRequest<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>url<span class="token punctuation">,</span> null<span class="token punctuation">,</span> JbootHttpRequest<span class="token punctuation">.</span>METHOD_GET<span class="token punctuation">)</span><span class="token punctuation">;</span>
    request<span class="token punctuation">.</span><span class="token function">setDownloadFile</span><span class="token punctuation">(</span>downloadToFile<span class="token punctuation">)</span><span class="token punctuation">;</span>

    JbootHttpResponse response <span class="token operator">=</span> Jboot<span class="token punctuation">.</span><span class="token function">me</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getHttp</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">handle</span><span class="token punctuation">(</span>request<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">if</span> <span class="token punctuation">(</span>response<span class="token punctuation">.</span><span class="token function">isError</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        downloadToFile<span class="token punctuation">.</span><span class="token function">delete</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>downloadToFile<span class="token punctuation">.</span><span class="token function">length</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><h1 id="metric数据监控"><a href="#metric数据监控" aria-hidden="true" class="header-anchor">#</a> metric数据监控</h1><p>Jboot的监控机制是通过metric来来做监控的，要启用metric非常简单，通过在jboot.properties文件配置上<code>jboot.metric.url</code>就可以启用metric。</p><p>例如</p><pre class="language-xml"><code>jboot.metric.url = /metric.html
</code></pre><p>我们就可以通过访问 <code>http://host:port/metric.html</code> 来访问到metric数据情况。</p><h3 id="添加metric数据"><a href="#添加metric数据" aria-hidden="true" class="header-anchor">#</a> 添加metric数据</h3><p>默认通过Url访问到的数据是没有具体内容，因为metric无法得知要显示什么样的数据内容。例如，我们要统计某个action的用户访问量，可以通过在action里编写如下代码。</p><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">myaction</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

    Jboot<span class="token punctuation">.</span><span class="token function">me</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getmetric</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">counter</span><span class="token punctuation">(</span><span class="token string">&quot;myaction&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">inc</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token function">renderText</span><span class="token punctuation">(</span><span class="token string">&quot;my action&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>当我们访问myaction这个地址后，然后再通过浏览器<code>http://host:port/metric.html</code>访问，我们就能查看到如下的json数据。</p><pre class="language-js"><code><span class="token punctuation">{</span>
	<span class="token string">&quot;version&quot;</span><span class="token punctuation">:</span> <span class="token string">&quot;3.1.3&quot;</span><span class="token punctuation">,</span>
	<span class="token string">&quot;gauges&quot;</span><span class="token punctuation">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
	<span class="token string">&quot;counters&quot;</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
		<span class="token string">&quot;myaction&quot;</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
				<span class="token string">&quot;count&quot;</span><span class="token punctuation">:</span> <span class="token number">1</span>
			<span class="token punctuation">}</span>
	<span class="token punctuation">}</span><span class="token punctuation">,</span>
	<span class="token string">&quot;histograms&quot;</span><span class="token punctuation">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
	<span class="token string">&quot;meters&quot;</span><span class="token punctuation">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
	<span class="token string">&quot;timers&quot;</span><span class="token punctuation">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>当再次访问<code>myaction</code>后，count里面的值就变成2了。</p><h3 id="metric与ganglia"><a href="#metric与ganglia" aria-hidden="true" class="header-anchor">#</a> metric与Ganglia</h3><h3 id="metric与grafana"><a href="#metric与grafana" aria-hidden="true" class="header-anchor">#</a> metric与Grafana</h3><h3 id="metric与jmx"><a href="#metric与jmx" aria-hidden="true" class="header-anchor">#</a> metric与jmx</h3><p>metric与jmx集成非常简单，只需要在jboot.properties文件添加如下配置：</p><pre class="language-xml"><code>jboot.metric.jmxReporter = true
</code></pre><p>然后，我们就可以通过<code>JConsole</code>或者<code>VisualVM</code>进行查看了。</p><h1 id="容错与隔离"><a href="#容错与隔离" aria-hidden="true" class="header-anchor">#</a> 容错与隔离</h1><h3 id="hystrix配置"><a href="#hystrix配置" aria-hidden="true" class="header-anchor">#</a> hystrix配置</h3><p>Jboot的容错、隔离和降级服务、都是通过<code>Hystrix</code>来实现的。在RPC远程调用中，Jboot已经默认开启了Hystrix的监控机制，对数默认错误率达到50%的service则立即返回，不走网络。</p><h3 id="hystrix-dashboard-部署"><a href="#hystrix-dashboard-部署" aria-hidden="true" class="header-anchor">#</a> Hystrix Dashboard 部署</h3><p>要查看hystrix的数据，我们需要部署<code>Hystrix Dashboard</code>。然后通过<code>Hystrix Dashboard</code>来查看。</p><p>通过Gradle来编译：</p><pre class="language-text"><code>$ git clone https://github.com/Netflix/Hystrix.git
$ cd Hystrix/hystrix-dashboard
$ ../gradlew appRun
&gt; Building &gt; :hystrix-dashboard:appRun &gt; Running at http://localhost:7979/hystrix-dashboard
</code></pre><p>或者通过docker来运行hystrix-dashboard:</p><pre class="language-java"><code>docker run <span class="token operator">--</span>rm <span class="token operator">-</span>ti <span class="token operator">-</span>p <span class="token number">7979</span><span class="token operator">:</span><span class="token number">7979</span> kennedyoliveira<span class="token operator">/</span>hystrix<span class="token operator">-</span>dashboard
</code></pre><p>运行<code>hystrix-dashboard</code>成功后，通过浏览器输入<code>http://localhost:7979/hystrix-dashboard</code>就可以看到如下图显示：</p><p><img src="https://github.com/Netflix/Hystrix/wiki/images/dashboard-home.png" alt></p><h3 id="通过-hystrix-dashboard-查看数据"><a href="#通过-hystrix-dashboard-查看数据" aria-hidden="true" class="header-anchor">#</a> 通过 Hystrix Dashboard 查看数据</h3><p>接下来，我们需要配置jboot应用的hystrix监控地址，配置如下：</p><pre class="language-text"><code>jboot.hystrix.url = /hystrix.stream
</code></pre><p>然后在上面图片中，填写url地址为：<code>http://host:port/hystrix.stream</code>,并点击<code>monitor stream</code>按钮,就可以看到如下图显示，所以的远程调用方法都统计到了。</p><p><strong>注意：</strong> 如果是通过docker启动的<code>hystrix-dashboard</code>，<code>http://host:port/hystrix.stream</code>中的host一定是本机的真实IP地址。</p><p><img src="https://github.com/Netflix/Hystrix/wiki/images/hystrix-dashboard-netflix-api-example-iPad.png" alt></p><h3 id="自定义监控隔离"><a href="#自定义监控隔离" aria-hidden="true" class="header-anchor">#</a> 自定义监控隔离</h3><h1 id="opentracing数据追踪"><a href="#opentracing数据追踪" aria-hidden="true" class="header-anchor">#</a> Opentracing数据追踪</h1><p>Jboot在分布式下，对数据的追踪是通过opentracing来实现的，opentracing官方地址（http://opentracing.io ）</p><h3 id="opentracing简介"><a href="#opentracing简介" aria-hidden="true" class="header-anchor">#</a> Opentracing简介</h3><p>OpenTracing（http://opentracing.io ）通过提供平台无关、厂商无关的API，使得开发人员能够方便的添加（或更换）追踪系统的实现。OpenTracing正在为全球的分布式追踪，提供统一的概念和数据标准。</p><p>目前，已经有了诸如 UBER，LightStep，Apple，yelp，workiva等公司在跟进，以及开源团队：ZIPKIN，appdash，TRACER，JAEGER，GRPC等的支持。</p><p>已经支持 opentracing-api的开源库有：Zipkin，Jaeger（Uber公司的），Appdash，LightStep，Hawkular，Instana，sky-walking，inspectIT，stagemonitor等。具体地址请查看：http://opentracing.io/documentation/pages/supported-tracers.html</p><h3 id="opentracing在jboot上的配置"><a href="#opentracing在jboot上的配置" aria-hidden="true" class="header-anchor">#</a> Opentracing在Jboot上的配置</h3><p>在jboot中启用opentracing非常简单，只需要做如下配置：</p><pre class="language-java"><code>jboot<span class="token punctuation">.</span>tracing<span class="token punctuation">.</span>type<span class="token operator">=</span>zipkin
jboot<span class="token punctuation">.</span>tracing<span class="token punctuation">.</span>serviceName<span class="token operator">=</span>service1
jboot<span class="token punctuation">.</span>tracing<span class="token punctuation">.</span>url<span class="token operator">=</span>http<span class="token operator">:</span><span class="token operator">/</span><span class="token operator">/</span><span class="token number">127.0</span><span class="token number">.0</span><span class="token number">.1</span><span class="token operator">:</span><span class="token number">9411</span><span class="token operator">/</span>api<span class="token operator">/</span>v2<span class="token operator">/</span>spans
</code></pre><p>同步简单几个配置，就可以启动opentracing对数据的追踪，并把数据传输到对应的服务器上，例如使用的是zipkin，那么就会传输到zipkin的server上。</p><h3 id="zipkin"><a href="#zipkin" aria-hidden="true" class="header-anchor">#</a> Zipkin</h3><p>zipkin官网： http://zipkin.io/</p><h4 id="zipkin快速启动"><a href="#zipkin快速启动" aria-hidden="true" class="header-anchor">#</a> zipkin快速启动</h4><pre class="language-java"><code>wget <span class="token operator">-</span>O zipkin<span class="token punctuation">.</span>jar <span class="token string">'https://search.maven.org/remote_content?g=io.zipkin.java&amp;a=zipkin-server&amp;v=LATEST&amp;c=exec'</span>
java <span class="token operator">-</span>jar zipkin<span class="token punctuation">.</span>jar
</code></pre><p>或者通过docker来运行：</p><pre class="language-java"><code>docker run <span class="token operator">-</span>d <span class="token operator">-</span>p <span class="token number">9411</span><span class="token operator">:</span><span class="token number">9411</span> openzipkin<span class="token operator">/</span>zipkin
</code></pre><p>或者 自己编译zipkin源代码，然后通过以下方式执行：</p><pre class="language-java"><code># Build the server and also make its dependencies
$ <span class="token punctuation">.</span>/mvnw <span class="token operator">-</span>DskipTests <span class="token operator">--</span>also<span class="token operator">-</span>make <span class="token operator">-</span>pl zipkin<span class="token operator">-</span>server clean install
# Run the server
$ java <span class="token operator">-</span>jar <span class="token punctuation">.</span>/zipkin<span class="token operator">-</span>server<span class="token operator">/</span>target<span class="token operator">/</span>zipkin<span class="token operator">-</span>server<span class="token operator">-</span><span class="token operator">*</span>exec<span class="token punctuation">.</span>jar
</code></pre><h4 id="使用zipkin"><a href="#使用zipkin" aria-hidden="true" class="header-anchor">#</a> 使用zipkin</h4><p>通过以上步骤，把zipkin启动后，只需要在 jboot.properties 文件把 jboot.tracing.url 的属性修改为zipkin的地址即可：</p><pre class="language-text"><code>jboot.tracing.url = http://127.0.0.1:9411/api/v2/spans
</code></pre><p>配置之后，我们就可以通过zipkin来查看jboot追踪的数据了。
<img src="http://zipkin.io/public/img/web-screenshot.png" alt></p><h3 id="skywalking"><a href="#skywalking" aria-hidden="true" class="header-anchor">#</a> SkyWalking</h3><p>SkyWalking官网：http://skywalking.org ，Skywalking为国人开发，据说目前 <strong>华为开发云</strong>、<strong>当当网</strong> 等已经 加入 Skywalking 生态系统，具体查看：https://www.oschina.net/news/89756/devcloud-dangdang-join-skywalking</p><h4 id="skywalking快速启动"><a href="#skywalking快速启动" aria-hidden="true" class="header-anchor">#</a> SkyWalking快速启动</h4><h4 id="使用skywalking"><a href="#使用skywalking" aria-hidden="true" class="header-anchor">#</a> 使用SkyWalking</h4><h3 id="其他"><a href="#其他" aria-hidden="true" class="header-anchor">#</a> 其他</h3><h1 id="统一配置中心"><a href="#统一配置中心" aria-hidden="true" class="header-anchor">#</a> 统一配置中心</h1><p>在jboot中，已经内置了统一配置中心，当中心配置文件修改后，分布式服务下的所有有用的额配置都会被修改。在某些情况下，如果统一配置中心出现宕机等情况，微服务将会使用本地配置文件当做当前配置信息。</p><h2 id="部署统一配置中心服务器"><a href="#部署统一配置中心服务器" aria-hidden="true" class="header-anchor">#</a> 部署统一配置中心服务器</h2><p>部署统一配置服务器非常简单，不需要写一行代码，把jboot.proerties的配置信息修改如下，并启动jboot，此时的jboot就已经是一个统一配置中心了。</p><pre class="language-text"><code>jboot.config.serverEnable=true
jboot.config.path=/Users/michael/Desktop/test
</code></pre><p>在以上配置中，我们可以把所有的配置文件(.properties文件)放到目录 <code>/Users/michael/Desktop/test</code> 目录下，当该目录下新增配置文件、修改配置文件、删除配置文件都会通过http暴露出去。</p><p>当启动 jboot 后，我们可以通过浏览器输入 <code>http://127.0.0.1:8080/jboot/config</code>来查看配置情况，微服务客户端也是定时访问这个url地址来读取配置信息。</p><h2 id="连接统一配置中心"><a href="#连接统一配置中心" aria-hidden="true" class="header-anchor">#</a> 连接统一配置中心</h2><p>要启用远程配置也非常简单，只需要在微服务添加下配置即可。</p><pre class="language-text"><code>jboot.config.remoteEnable=true
jboot.config.remoteUrl=http://127.0.0.1:8080/jboot/config
</code></pre><p>当启用远程配置后，服务会优先使用远程配置，在远程配置未配置 或 宕机的情况下使用本地配置。</p><h1 id="swagger-api自动生成"><a href="#swagger-api自动生成" aria-hidden="true" class="header-anchor">#</a> Swagger api自动生成</h1><h2 id="swagger简介"><a href="#swagger简介" aria-hidden="true" class="header-anchor">#</a> swagger简介</h2><h2 id="swagger使用"><a href="#swagger使用" aria-hidden="true" class="header-anchor">#</a> swagger使用</h2><h3 id="第一步：配置并启用swagger"><a href="#第一步：配置并启用swagger" aria-hidden="true" class="header-anchor">#</a> 第一步：配置并启用swagger</h3><p>在 jboot.properties上添加如下配置：</p><pre class="language-java"><code>jboot<span class="token punctuation">.</span>swagger<span class="token punctuation">.</span>path<span class="token operator">=</span><span class="token operator">/</span>swaggerui
jboot<span class="token punctuation">.</span>swagger<span class="token punctuation">.</span>title<span class="token operator">=</span>Jboot API 测试
jboot<span class="token punctuation">.</span>swagger<span class="token punctuation">.</span>description<span class="token operator">=</span>这真的真的真的只是一个测试而已，不要当真。
jboot<span class="token punctuation">.</span>swagger<span class="token punctuation">.</span>version<span class="token operator">=</span><span class="token number">1.0</span>
jboot<span class="token punctuation">.</span>swagger<span class="token punctuation">.</span>termsOfService<span class="token operator">=</span>http<span class="token operator">:</span><span class="token operator">/</span><span class="token operator">/</span>jboot<span class="token punctuation">.</span>io
jboot<span class="token punctuation">.</span>swagger<span class="token punctuation">.</span>contact<span class="token operator">=</span>email<span class="token operator">:</span>fuhai999<span class="token annotation punctuation">@gmail</span><span class="token punctuation">.</span>com<span class="token punctuation">;</span>qq<span class="token operator">:</span><span class="token number">123456</span>
jboot<span class="token punctuation">.</span>swagger<span class="token punctuation">.</span>host<span class="token operator">=</span><span class="token number">127.0</span><span class="token number">.0</span><span class="token number">.1</span><span class="token operator">:</span><span class="token number">8080</span> 
</code></pre><h3 id="第二步：下载swagger-ui放到resource目录下"><a href="#第二步：下载swagger-ui放到resource目录下" aria-hidden="true" class="header-anchor">#</a> 第二步：下载swagger ui放到resource目录下</h3><p>注意，这里一定要放在resource的 <code>swaggerui</code> 目录，因为以上的配置中是<code>jboot.swagger.path=/swaggerui</code>,当然可以通过这个配置来修改这个存放目录。</p><p>另：swagger ui 的下载地址是：https://github.com/swagger-api/swagger-ui，下载其 <code>dist</code> 目录即可，只需要这个目录里的文件。</p><h3 id="第三步：通过注解配置controller的api"><a href="#第三步：通过注解配置controller的api" aria-hidden="true" class="header-anchor">#</a> 第三步：通过注解配置Controller的api</h3><p>代码如下：</p><pre class="language-java"><code><span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/swaggerTest&quot;</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@Api</span><span class="token punctuation">(</span>description <span class="token operator">=</span> <span class="token string">&quot;用户相关接口文档&quot;</span><span class="token punctuation">,</span> basePath <span class="token operator">=</span> <span class="token string">&quot;/swaggerTest&quot;</span><span class="token punctuation">,</span> tags <span class="token operator">=</span> <span class="token string">&quot;abc&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MySwaggerTestController</span> <span class="token keyword">extends</span> <span class="token class-name">JbootController</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@ApiOperation</span><span class="token punctuation">(</span>value <span class="token operator">=</span> <span class="token string">&quot;用户列表&quot;</span><span class="token punctuation">,</span> httpMethod <span class="token operator">=</span> <span class="token string">&quot;GET&quot;</span><span class="token punctuation">,</span> notes <span class="token operator">=</span> <span class="token string">&quot;user list&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">index</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">renderJson</span><span class="token punctuation">(</span>Ret<span class="token punctuation">.</span><span class="token function">ok</span><span class="token punctuation">(</span><span class="token string">&quot;k1&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;v1&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">&quot;name&quot;</span><span class="token punctuation">,</span> <span class="token function">getPara</span><span class="token punctuation">(</span><span class="token string">&quot;name&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>


    <span class="token annotation punctuation">@ApiOperation</span><span class="token punctuation">(</span>value <span class="token operator">=</span> <span class="token string">&quot;添加用户&quot;</span><span class="token punctuation">,</span> httpMethod <span class="token operator">=</span> <span class="token string">&quot;POST&quot;</span><span class="token punctuation">,</span> notes <span class="token operator">=</span> <span class="token string">&quot;add user&quot;</span><span class="token punctuation">)</span>
    <span class="token annotation punctuation">@ApiImplicitParams</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
            <span class="token annotation punctuation">@ApiImplicitParam</span><span class="token punctuation">(</span>name <span class="token operator">=</span> <span class="token string">&quot;username&quot;</span><span class="token punctuation">,</span> value <span class="token operator">=</span> <span class="token string">&quot;用户名&quot;</span><span class="token punctuation">,</span> paramType <span class="token operator">=</span> <span class="token string">&quot;form&quot;</span><span class="token punctuation">,</span> dataType <span class="token operator">=</span> <span class="token string">&quot;string&quot;</span><span class="token punctuation">,</span> required <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
            <span class="token annotation punctuation">@ApiImplicitParam</span><span class="token punctuation">(</span>name <span class="token operator">=</span> <span class="token string">&quot;k1&quot;</span><span class="token punctuation">,</span> value <span class="token operator">=</span> <span class="token string">&quot;k1&quot;</span><span class="token punctuation">,</span> paramType <span class="token operator">=</span> <span class="token string">&quot;form&quot;</span><span class="token punctuation">,</span> dataType <span class="token operator">=</span> <span class="token string">&quot;string&quot;</span><span class="token punctuation">,</span> required <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">add</span><span class="token punctuation">(</span>String username<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">renderJson</span><span class="token punctuation">(</span>Ret<span class="token punctuation">.</span><span class="token function">ok</span><span class="token punctuation">(</span><span class="token string">&quot;k1&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;v1&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">&quot;username&quot;</span><span class="token punctuation">,</span> username<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>


<span class="token punctuation">}</span>
</code></pre><h3 id="第四步：浏览器访问swagger生成api文档"><a href="#第四步：浏览器访问swagger生成api文档" aria-hidden="true" class="header-anchor">#</a> 第四步：浏览器访问swagger生成api文档</h3><p>在第一步的配置中，因为<code>jboot.swagger.path=/swaggerui</code>，所以我们访问如下地址：<code>http://127.0.0.1:8080/swaggerui</code> 效果如下图所示。</p><p><img src="http://oss.yangfuhai.com/markdown/jboot/swagger/01.png" alt>
图片1</p><p><img src="http://oss.yangfuhai.com/markdown/jboot/swagger/02.png" alt>
图片2</p><p>在图片2中，我们可以输入参数，并点击 <code>Execute</code> 按钮进行测试。</p><h1 id="其他-2"><a href="#其他-2" aria-hidden="true" class="header-anchor">#</a> 其他</h1><h2 id="spi扩展"><a href="#spi扩展" aria-hidden="true" class="header-anchor">#</a> SPI扩展</h2><p>SPI的全名为Service Provider Interface。</p><h3 id="spi具体约定"><a href="#spi具体约定" aria-hidden="true" class="header-anchor">#</a> SPI具体约定</h3><p>当服务的提供者，提供了服务接口的一种实现之后，在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而jboot装配这个模块的时候，就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名，并装载实例化，完成模块的注入。</p><h3 id="jboot-spi模块"><a href="#jboot-spi模块" aria-hidden="true" class="header-anchor">#</a> Jboot SPI模块</h3><p>在jboot中，一下模块已经实现了SPI机制。</p><ul><li>Jbootrpc</li><li>JbootHttp</li><li>JbootCache</li><li>Jbootmq</li><li>JbootSerializer</li></ul><p>例如，在JbootCache中，内置了三种实现方案：ehcache、redis、ehredis。在配置文件中，我看可以通过 <code>jboot.cache.type = ehcache</code> 的方式来指定在Jboot应用中使用了什么样的缓存方案。</p><p>但是，在Jboot中，通过SPI机制，我们一样可以扩展出第4、第5甚至更多的缓存方案出来。</p><p>扩展步骤如下：</p><ul><li>第一步：编写JbootCache的子类</li><li>第二步：通过@JbootSpi注解给刚刚编写的类设置上一个名字，例如：mycache</li><li>第三步：通过在jboot.properties文件中配置上类型为 mycache，配置代码如下：</li></ul><pre class="language-xml"><code>jboot.cache.type = mycache
</code></pre><p>通过以上三步，我们就可以完成了对JbootCache模块的扩展，其他模块类似。</p><h2 id="jbootevnet事件机制"><a href="#jbootevnet事件机制" aria-hidden="true" class="header-anchor">#</a> JbootEvnet事件机制</h2><p>为了解耦，Jboot内置了一个简单易用的事件系统，使用事件系统非常简单。</p><h4 id="第一步，注册事件的监听器。"><a href="#第一步，注册事件的监听器。" aria-hidden="true" class="header-anchor">#</a> 第一步，注册事件的监听器。</h4><pre class="language-java"><code><span class="token annotation punctuation">@EventConfig</span><span class="token punctuation">(</span>action <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token string">&quot;event1&quot;</span><span class="token punctuation">,</span><span class="token string">&quot;event2&quot;</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MyEventListener</span> <span class="token keyword">implements</span> <span class="token class-name">JbootEventListener</span> <span class="token punctuation">{</span>
    
    <span class="token keyword">public</span>  <span class="token keyword">void</span> <span class="token function">onEvent</span><span class="token punctuation">(</span>JbootEvent event<span class="token punctuation">)</span><span class="token punctuation">{</span>
        Object data <span class="token operator">=</span> event<span class="token punctuation">.</span><span class="token function">getData</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">&quot;get data:&quot;</span><span class="token operator">+</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>通过 @EventConfig 配置 让MyEventListener监听上 event1和event2两个事件。</p><h4 id="第二步，在项目任何地方发生事件"><a href="#第二步，在项目任何地方发生事件" aria-hidden="true" class="header-anchor">#</a> 第二步，在项目任何地方发生事件</h4><pre class="language-java"><code>Jboot<span class="token punctuation">.</span><span class="token function">sendEvent</span><span class="token punctuation">(</span><span class="token string">&quot;event1&quot;</span><span class="token punctuation">,</span>  object<span class="token punctuation">)</span>
</code></pre><h2 id="自定义序列化"><a href="#自定义序列化" aria-hidden="true" class="header-anchor">#</a> 自定义序列化</h2><p>自定义序列化是通过Jboot的SPI机制来实现的，请参考 <a href="#SPI%E6%89%A9%E5%B1%95">SPI扩展</a>。</p><h2 id="配置文件"><a href="#配置文件" aria-hidden="true" class="header-anchor">#</a> 配置文件</h2><h3 id="读取jboot-properties的配置信息"><a href="#读取jboot-properties的配置信息" aria-hidden="true" class="header-anchor">#</a> 读取jboot.properties的配置信息</h3><p>要读取jboot.properties的配置信息非常简单，例如我们配置内容如下：</p><pre class="language-xml"><code>jboot.myconfig.name=aaa
jboot.myconfig.passowrd=bbb
jboot.myconfig.age=10
</code></pre><p>要读取这个配置信息，我们需要定义我们的一个model类，并通过@PropertyConfig注解给我们的类配置上类与配置文件的对应关系，如下所示：</p><pre class="language-java"><code><span class="token annotation punctuation">@PropertyConfig</span><span class="token punctuation">(</span>prefix<span class="token operator">=</span><span class="token string">&quot;jboot.myconfig&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MyConfigModel</span><span class="token punctuation">{</span>
    <span class="token keyword">private</span> String name<span class="token punctuation">;</span>
    <span class="token keyword">private</span> String password<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token keyword">int</span> age<span class="token punctuation">;</span>

    <span class="token comment">//getter setter 略</span>
<span class="token punctuation">}</span>
</code></pre><p><em>注意：</em> 类名MyConfigModel随便取</p><p>编写好配置类MyConfigModel后，我们就可以通过如下代码来读取到配置信息：</p><pre class="language-java"><code>MyConfigModel config <span class="token operator">=</span> Jboot<span class="token punctuation">.</span><span class="token function">config</span><span class="token punctuation">(</span>MyConfigModel<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><h3 id="读取自定义配置文件的配置信息"><a href="#读取自定义配置文件的配置信息" aria-hidden="true" class="header-anchor">#</a> 读取自定义配置文件的配置信息</h3><p>在以上章节中，我们已经知道了如何来读取jboot.properties的配置文件，在某些场景下，可能需要我们把我们的配置信息编写到一个独立的properties配置文件里面去，例如：在我们的项目中有一个叫 michael.properties 文件，文件的内容如下：</p><pre class="language-xml"><code>jboot.myconfig.name=aaa
jboot.myconfig.passowrd=bbb
jboot.myconfig.age=10
</code></pre><p>那么，一样的，我们需要编写一个model，并配置上@PropertyConfig注解，与读取jboot.properties文件不同的是，@PropertyConfig 需要添加上file配置，内容如下：</p><pre class="language-java"><code><span class="token annotation punctuation">@PropertyConfig</span><span class="token punctuation">(</span>prefix<span class="token operator">=</span><span class="token string">&quot;jboot.myconfig&quot;</span><span class="token punctuation">,</span>file<span class="token operator">=</span><span class="token string">&quot;michael.properties&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MyConfigModel</span><span class="token punctuation">{</span>
    <span class="token keyword">private</span> String name<span class="token punctuation">;</span>
    <span class="token keyword">private</span> String password<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token keyword">int</span> age<span class="token punctuation">;</span>

    <span class="token comment">//getter setter 略</span>
<span class="token punctuation">}</span>
</code></pre><p>然后，和读取jboot.properties一样。</p><pre class="language-java"><code>MyConfigModel config <span class="token operator">=</span> Jboot<span class="token punctuation">.</span><span class="token function">config</span><span class="token punctuation">(</span>MyConfigModel<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><h2 id="分布式session-2"><a href="#分布式session-2" aria-hidden="true" class="header-anchor">#</a> 分布式session</h2><h2 id="代码生成器"><a href="#代码生成器" aria-hidden="true" class="header-anchor">#</a> 代码生成器</h2><p>Jboot内置了一个简易的代码生成器，可以用来生成model层和Service层的基础代码，在生成代码之前，请先配置jboot.properties关于数据库相关的配置信息。</p><h3 id="使用步骤-2"><a href="#使用步骤-2" aria-hidden="true" class="header-anchor">#</a> 使用步骤</h3><h4 id="第一步：配置数据源"><a href="#第一步：配置数据源" aria-hidden="true" class="header-anchor">#</a> 第一步：配置数据源</h4><pre class="language-xml"><code>jboot.datasource.type=mysql
jboot.datasource.url=jdbc:mysql://127.0.0.1:3306/jbootdemo
jboot.datasource.user=root
jboot.datasource.password=your_password
</code></pre><h4 id="第二步：通过jbootmodelgenerator生成model代码"><a href="#第二步：通过jbootmodelgenerator生成model代码" aria-hidden="true" class="header-anchor">#</a> 第二步：通过JbootModelGenerator生成model代码</h4><pre class="language-java"><code>  <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  
  		<span class="token comment">//model 的包名</span>
        String modelPackage <span class="token operator">=</span> <span class="token string">&quot;io.jboot.test&quot;</span><span class="token punctuation">;</span>
        
        JbootModelGenerator<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span>modelPackage<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token punctuation">}</span>
</code></pre><h4 id="第三步：通过jbootservicegenerator生成service代码"><a href="#第三步：通过jbootservicegenerator生成service代码" aria-hidden="true" class="header-anchor">#</a> 第三步：通过JbootServiceGenerator生成Service代码</h4><pre class="language-java"><code>  <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  
  		<span class="token comment">//生成service 的包名</span>
        String basePackage <span class="token operator">=</span> <span class="token string">&quot;io.jboot.testservice&quot;</span><span class="token punctuation">;</span>
        <span class="token comment">//依赖model的包名</span>
        String modelPackage <span class="token operator">=</span> <span class="token string">&quot;io.jboot.test&quot;</span><span class="token punctuation">;</span>
        
        JbootServiceGenerator<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span>basePackage<span class="token punctuation">,</span> modelPackage<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token punctuation">}</span>
</code></pre><h4 id="其他-3"><a href="#其他-3" aria-hidden="true" class="header-anchor">#</a> 其他</h4><p>当没在jboot.properties文件配置数据源的时候，可以通过如下代码来使用：</p><pre class="language-java"><code> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>

        Jboot<span class="token punctuation">.</span><span class="token function">setBootArg</span><span class="token punctuation">(</span><span class="token string">&quot;jboot.datasource.url&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;jdbc:mysql://127.0.0.1:3306/jbootdemo&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        Jboot<span class="token punctuation">.</span><span class="token function">setBootArg</span><span class="token punctuation">(</span><span class="token string">&quot;jboot.datasource.user&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;root&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        String basePackage <span class="token operator">=</span> <span class="token string">&quot;io.jboot.codegen.service.test&quot;</span><span class="token punctuation">;</span>
        String modelPackage <span class="token operator">=</span> <span class="token string">&quot;io.jboot.codegen.test.model&quot;</span><span class="token punctuation">;</span>
        JbootServiceGenerator<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span>basePackage<span class="token punctuation">,</span> modelPackage<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token punctuation">}</span>

</code></pre><h1 id="项目构建"><a href="#项目构建" aria-hidden="true" class="header-anchor">#</a> 项目构建</h1><p>在Jboot中已经内置了高性能服务器undertow，undertow的性能比tomcat高出很多（具体自行搜索：undertow vs tomcat），所以jboot构建和部署等不再需要tomcat。在Jboot构建的时候，在linux平台下，会生成jboot.sh 在windows平台下会生成jboot.bat脚本，直接执行该脚本即可。</p><p>生成jboot.sh或者jboot.bat，依赖maven的appassembler插件，因此，你的maven配置文件pom.xml需要添加如下配置：</p><p>config pom.xml</p><pre class="language-xml"><code>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>build</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>plugins</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>plugin</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.apache.maven.plugins<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>maven-compiler-plugin<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>configuration</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>source</span><span class="token punctuation">&gt;</span></span>1.8<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>source</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>target</span><span class="token punctuation">&gt;</span></span>1.8<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>target</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>encoding</span><span class="token punctuation">&gt;</span></span>UTF-8<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>encoding</span><span class="token punctuation">&gt;</span></span>
                <span class="token comment">&lt;!--必须添加compilerArgument配置，才能使用JFinal的Controller方法带参数的功能--&gt;</span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>compilerArgument</span><span class="token punctuation">&gt;</span></span>-parameters<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>compilerArgument</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>configuration</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>plugin</span><span class="token punctuation">&gt;</span></span>


        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>plugin</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.codehaus.mojo<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>appassembler-maven-plugin<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>version</span><span class="token punctuation">&gt;</span></span>1.10<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>version</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>configuration</span><span class="token punctuation">&gt;</span></span>
            
               <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>assembleDirectory</span><span class="token punctuation">&gt;</span></span>${project.build.directory}/app<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>assembleDirectory</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>repositoryName</span><span class="token punctuation">&gt;</span></span>lib<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>repositoryName</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>binFolder</span><span class="token punctuation">&gt;</span></span>bin<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>binFolder</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>configurationDirectory</span><span class="token punctuation">&gt;</span></span>webRoot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>configurationDirectory</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>copyConfigurationDirectory</span><span class="token punctuation">&gt;</span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>copyConfigurationDirectory</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>configurationSourceDirectory</span><span class="token punctuation">&gt;</span></span>src/main/resources<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>configurationSourceDirectory</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>repositoryLayout</span><span class="token punctuation">&gt;</span></span>flat<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>repositoryLayout</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>encoding</span><span class="token punctuation">&gt;</span></span>UTF-8<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>encoding</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>logsDirectory</span><span class="token punctuation">&gt;</span></span>logs<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>logsDirectory</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>tempDirectory</span><span class="token punctuation">&gt;</span></span>tmp<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>tempDirectory</span><span class="token punctuation">&gt;</span></span>

                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>programs</span><span class="token punctuation">&gt;</span></span>
                    <span class="token comment">&lt;!--程序打包 mvn package appassembler:assemble --&gt;</span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>program</span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>mainClass</span><span class="token punctuation">&gt;</span></span>io.jboot.Jboot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>mainClass</span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>id</span><span class="token punctuation">&gt;</span></span>jboot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>id</span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>platforms</span><span class="token punctuation">&gt;</span></span>
                            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>platform</span><span class="token punctuation">&gt;</span></span>windows<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>platform</span><span class="token punctuation">&gt;</span></span>
                            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>platform</span><span class="token punctuation">&gt;</span></span>unix<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>platform</span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>platforms</span><span class="token punctuation">&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>program</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>programs</span><span class="token punctuation">&gt;</span></span>

                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>daemons</span><span class="token punctuation">&gt;</span></span>
                    <span class="token comment">&lt;!-- 后台程序打包：mvn clean package appassembler:generate-daemons --&gt;</span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>daemon</span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>mainClass</span><span class="token punctuation">&gt;</span></span>io.jboot.Jboot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>mainClass</span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>id</span><span class="token punctuation">&gt;</span></span>jboot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>id</span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>platforms</span><span class="token punctuation">&gt;</span></span>
                            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>platform</span><span class="token punctuation">&gt;</span></span>jsw<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>platform</span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>platforms</span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>generatorConfigurations</span><span class="token punctuation">&gt;</span></span>
                            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>generatorConfiguration</span><span class="token punctuation">&gt;</span></span>
                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>generator</span><span class="token punctuation">&gt;</span></span>jsw<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>generator</span><span class="token punctuation">&gt;</span></span>
                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>includes</span><span class="token punctuation">&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>include</span><span class="token punctuation">&gt;</span></span>linux-x86-32<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>include</span><span class="token punctuation">&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>include</span><span class="token punctuation">&gt;</span></span>linux-x86-64<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>include</span><span class="token punctuation">&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>include</span><span class="token punctuation">&gt;</span></span>macosx-universal-32<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>include</span><span class="token punctuation">&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>include</span><span class="token punctuation">&gt;</span></span>macosx-universal-64<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>include</span><span class="token punctuation">&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>include</span><span class="token punctuation">&gt;</span></span>windows-x86-32<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>include</span><span class="token punctuation">&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>include</span><span class="token punctuation">&gt;</span></span>windows-x86-64<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>include</span><span class="token punctuation">&gt;</span></span>
                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>includes</span><span class="token punctuation">&gt;</span></span>
                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>configuration</span><span class="token punctuation">&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>property</span><span class="token punctuation">&gt;</span></span>
                                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>name</span><span class="token punctuation">&gt;</span></span>configuration.directory.in.classpath.first<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>name</span><span class="token punctuation">&gt;</span></span>
                                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>value</span><span class="token punctuation">&gt;</span></span>webRoot<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>value</span><span class="token punctuation">&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>property</span><span class="token punctuation">&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>property</span><span class="token punctuation">&gt;</span></span>
                                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>name</span><span class="token punctuation">&gt;</span></span>wrapper.ping.timeout<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>name</span><span class="token punctuation">&gt;</span></span>
                                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>value</span><span class="token punctuation">&gt;</span></span>120<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>value</span><span class="token punctuation">&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>property</span><span class="token punctuation">&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>property</span><span class="token punctuation">&gt;</span></span>
                                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>name</span><span class="token punctuation">&gt;</span></span>set.default.REPO_DIR<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>name</span><span class="token punctuation">&gt;</span></span>
                                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>value</span><span class="token punctuation">&gt;</span></span>lib<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>value</span><span class="token punctuation">&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>property</span><span class="token punctuation">&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>property</span><span class="token punctuation">&gt;</span></span>
                                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>name</span><span class="token punctuation">&gt;</span></span>wrapper.logfile<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>name</span><span class="token punctuation">&gt;</span></span>
                                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>value</span><span class="token punctuation">&gt;</span></span>logs/wrapper.log<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>value</span><span class="token punctuation">&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>property</span><span class="token punctuation">&gt;</span></span>
                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>configuration</span><span class="token punctuation">&gt;</span></span>
                            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>generatorConfiguration</span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>generatorConfigurations</span><span class="token punctuation">&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>daemon</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>daemons</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>configuration</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>plugin</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>plugins</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>build</span><span class="token punctuation">&gt;</span></span>
</code></pre><h4 id="进行maven构建"><a href="#进行maven构建" aria-hidden="true" class="header-anchor">#</a> 进行maven构建</h4><pre class="language-java"><code>mvn <span class="token keyword">package</span> appassembler<span class="token operator">:</span>assemble
</code></pre><p>构建完毕后，会在target目录下生成一个app文件夹，在app文件的bin目录下会有一个jboot脚本（或者jboot.bat）。</p><h4 id="启动应用"><a href="#启动应用" aria-hidden="true" class="header-anchor">#</a> 启动应用</h4><pre class="language-java"><code>cd yourProjectPath<span class="token operator">/</span>target<span class="token operator">/</span>app<span class="token operator">/</span>bin
<span class="token punctuation">.</span>/jboot
</code></pre><h5 id="在启动的时候添加上自己的配置信息"><a href="#在启动的时候添加上自己的配置信息" aria-hidden="true" class="header-anchor">#</a> 在启动的时候添加上自己的配置信息</h5><pre class="language-java"><code>cd yourProjectPath<span class="token operator">/</span>target<span class="token operator">/</span>app<span class="token operator">/</span>bin
<span class="token punctuation">.</span>/jboot <span class="token operator">--</span>jboot<span class="token punctuation">.</span>server<span class="token punctuation">.</span>port<span class="token operator">=</span><span class="token number">8080</span> <span class="token operator">--</span>jboot<span class="token punctuation">.</span>rpc<span class="token punctuation">.</span>type<span class="token operator">=</span>local
</code></pre><h5 id="使用你自己的配置文件来代替-jboot-properties"><a href="#使用你自己的配置文件来代替-jboot-properties" aria-hidden="true" class="header-anchor">#</a> 使用你自己的配置文件来代替 jboot.properties</h5><pre class="language-java"><code>cd yourProjectPath<span class="token operator">/</span>target<span class="token operator">/</span>app<span class="token operator">/</span>bin
<span class="token punctuation">.</span>/jboot <span class="token operator">--</span>jboot<span class="token punctuation">.</span>model<span class="token operator">=</span>dev <span class="token operator">--</span>jboot<span class="token punctuation">.</span>server<span class="token punctuation">.</span>port<span class="token operator">=</span><span class="token number">8080</span>
</code></pre><p>上面的命令启动后，会使用 <code>jboot-dev.proerties</code> 文件来替代 <code>jboot.properties</code> 同时设置 jboot.server.port=8080（服务器端口号为8080）</p><h4 id="后台程序"><a href="#后台程序" aria-hidden="true" class="header-anchor">#</a> 后台程序</h4><p>在以上文档中，如果通过如下代码进行构建的。</p><pre class="language-java"><code>mvn <span class="token keyword">package</span> appassembler<span class="token operator">:</span>assemble
</code></pre><p>构建会生成 app目录，及对应的jboot脚本，但是jboot在执行的时候是前台执行的，也就是必须打开一个窗口，当关闭这个窗口后，jboot内置的服务器undertow也会随之关闭了，在正式的环境里，我们是希望它能够以服务的方式在后台运行。</p><p>那么，如果构建一个后台运行的程序呢？步骤如下：</p><h5 id="第一步：执行如下maven编译"><a href="#第一步：执行如下maven编译" aria-hidden="true" class="header-anchor">#</a> 第一步：执行如下maven编译</h5><pre class="language-java"><code>mvn clean <span class="token keyword">package</span> appassembler<span class="token operator">:</span>generate<span class="token operator">-</span>daemons
</code></pre><p>maven命令执行完毕后，会在target下生成如下文件夹 <code>/generated-resources/appassembler/jsw/jboot</code> , 文件中我们会找到bin目录，生成的后台脚本jboot（或jboot.bat）会存放在bin目录里。</p><h5 id="第二步：启动应用"><a href="#第二步：启动应用" aria-hidden="true" class="header-anchor">#</a> 第二步：启动应用</h5><pre class="language-java"><code>cd yourProjectPath<span class="token operator">/</span>target<span class="token operator">/</span>generated<span class="token operator">-</span>resources<span class="token operator">/</span>appassembler<span class="token operator">/</span>jsw<span class="token operator">/</span>jboot<span class="token operator">/</span>bin
<span class="token punctuation">.</span>/jboot
</code></pre><p>此时，启动的应用为后台程序了。</p><h2 id="jboot部署到tomcat"><a href="#jboot部署到tomcat" aria-hidden="true" class="header-anchor">#</a> Jboot部署到tomcat</h2><p>首先，需要配置的自己的pom文件的packaging为war，并配置上maven编译插件：</p><pre class="language-xml"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>plugin</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>groupId</span><span class="token punctuation">&gt;</span></span>org.apache.maven.plugins<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>groupId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>maven-war-plugin<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>configuration</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>attachClasses</span><span class="token punctuation">&gt;</span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>attachClasses</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>packagingExcludes</span><span class="token punctuation">&gt;</span></span>WEB-INF/web.xml<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>packagingExcludes</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>configuration</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>plugin</span><span class="token punctuation">&gt;</span></span>

</code></pre><p>这个过程和普通的java web工程没什么区别。</p><p>最最重要的是配置web.xml，在WEB-INF下创建 web.xml，起内容如下：</p><pre class="language-xml"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>filter</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>filter-name</span><span class="token punctuation">&gt;</span></span>jfinal<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>filter-name</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>filter-class</span><span class="token punctuation">&gt;</span></span>com.jfinal.core.JFinalFilter<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>filter-class</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>init-param</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>param-name</span><span class="token punctuation">&gt;</span></span>configClass<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>param-name</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>param-value</span><span class="token punctuation">&gt;</span></span>io.jboot.web.JbootAppConfig<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>param-value</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>init-param</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>filter</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>filter-mapping</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>filter-name</span><span class="token punctuation">&gt;</span></span>jfinal<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>filter-name</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>url-pattern</span><span class="token punctuation">&gt;</span></span>/*<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>url-pattern</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>filter-mapping</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>这里注意：param-value一定使用io.jboot.web.JbootAppConfig，或者是其子类。</p><p>如果用到shiro，再配置上：</p><pre class="language-xml"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>filter</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>filter-name</span><span class="token punctuation">&gt;</span></span>shiro<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>filter-name</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>filter-class</span><span class="token punctuation">&gt;</span></span>org.apache.shiro.web.servlet.ShiroFilter<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>filter-class</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>filter</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>filter-mapping</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>filter-name</span><span class="token punctuation">&gt;</span></span>shiro<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>filter-name</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>url-pattern</span><span class="token punctuation">&gt;</span></span>/*<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>url-pattern</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>filter-mapping</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>listener</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>listener-class</span><span class="token punctuation">&gt;</span></span>org.apache.shiro.web.env.EnvironmentLoaderListener<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>listener-class</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>listener</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>一般情况下，shiro的配置内容要放到jfinal的配置之上。</p><p>如果项目还用到hystrix，需要添加如下配置：</p><pre class="language-xml"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>servlet</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>servlet-name</span><span class="token punctuation">&gt;</span></span>hystrix<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>servlet-name</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>servlet-class</span><span class="token punctuation">&gt;</span></span>com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>servlet-class</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>servlet</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>servlet-mapping</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>servlet-name</span><span class="token punctuation">&gt;</span></span>hystrix<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>servlet-name</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>url-pattern</span><span class="token punctuation">&gt;</span></span>/hystrix<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>url-pattern</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>servlet-mapping</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>如果还用到Metrics，添加如下配置：</p><pre class="language-xml"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>servlet</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>servlet-name</span><span class="token punctuation">&gt;</span></span>metrics<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>servlet-name</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>servlet-class</span><span class="token punctuation">&gt;</span></span>com.codahale.metrics.servlets.AdminServlet<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>servlet-class</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>servlet</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>servlet-mapping</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>servlet-name</span><span class="token punctuation">&gt;</span></span>metrics<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>servlet-name</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>url-pattern</span><span class="token punctuation">&gt;</span></span>/metrics<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>url-pattern</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>servlet-mapping</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>listener</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>listener-class</span><span class="token punctuation">&gt;</span></span>io.jboot.component.metric.JbootMetricServletContextListener<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>listener-class</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>listener</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>listener</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>listener-class</span><span class="token punctuation">&gt;</span></span>io.jboot.component.metric.JbootHealthCheckServletContextListener<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>listener-class</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>listener</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>注意：因为项目的html文件都放在resource下，如果war解压后只有 META-INF 和 WEB-INF 这两个文件夹，html文件被打包在 WEB-INF/clasess 下，是不会被正确渲染的。所以需要通过pom文件配置插件，把resource下的html文件copy到war的根目录下，才能被正常渲染。</p><p>假设你的html文件都放在 resource下的htmls目录，配置内容如下：</p><pre class="language-xml"><code> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>plugin</span><span class="token punctuation">&gt;</span></span>
   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>artifactId</span><span class="token punctuation">&gt;</span></span>maven-antrun-plugin<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>artifactId</span><span class="token punctuation">&gt;</span></span>
   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>executions</span><span class="token punctuation">&gt;</span></span>
       <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>execution</span><span class="token punctuation">&gt;</span></span>
           <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>phase</span><span class="token punctuation">&gt;</span></span>compile<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>phase</span><span class="token punctuation">&gt;</span></span>
           <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>goals</span><span class="token punctuation">&gt;</span></span>
               <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>goal</span><span class="token punctuation">&gt;</span></span>run<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>goal</span><span class="token punctuation">&gt;</span></span>
           <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>goals</span><span class="token punctuation">&gt;</span></span>
           <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>configuration</span><span class="token punctuation">&gt;</span></span>
               <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>tasks</span><span class="token punctuation">&gt;</span></span>
                   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>move</span> <span class="token attr-name">file</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>${project.build.directory}/classes/htmls<span class="token punctuation">&quot;</span></span>  <span class="token attr-name">tofile</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>${project.build.directory}/${project.build.finalName}/htmls<span class="token punctuation">&quot;</span></span><span class="token punctuation">/&gt;</span></span>
               <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>tasks</span><span class="token punctuation">&gt;</span></span>
           <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>configuration</span><span class="token punctuation">&gt;</span></span>
       <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>execution</span><span class="token punctuation">&gt;</span></span>
   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>executions</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>plugin</span><span class="token punctuation">&gt;</span></span>
</code></pre><h1 id="鸣谢"><a href="#鸣谢" aria-hidden="true" class="header-anchor">#</a> 鸣谢</h1><p>rpc framework:</p><ul><li>motan(https://github.com/weibocom/motan)</li><li>grpc(http://grpc.io)</li><li>thrift(https://github.com/apache/thrift)</li></ul><p>mq framework:</p><ul><li>activemq</li><li>rabbitmq</li><li>redis mq</li><li>hornetq</li><li>aliyun mq</li></ul><p>cache framework</p><ul><li>ehcache</li><li>redis</li></ul><p>core framework:</p><ul><li>jfinal (https://github.com/jfinal/jfinal)</li><li>undertow (https://github.com/undertow-io/undertow)</li><li>guice (https://github.com/google/guice)</li><li>metrics (https://github.com/dropwizard/metrics)</li><li>hystrix (https://github.com/Netflix/Hystrix)</li><li>shiro （https://github.com/apache/shiro）</li></ul><h1 id="联系作者"><a href="#联系作者" aria-hidden="true" class="header-anchor">#</a> 联系作者</h1><ul><li>qq:1506615067</li><li>wechat：wx198819880</li><li>email:fuhai999#gmail.com</li></ul><h1 id="常见问题"><a href="#常见问题" aria-hidden="true" class="header-anchor">#</a> 常见问题</h1><ul><li>使用Jboot后还能自定义Jfinal的配置文件吗？
<ul><li>答：可以使用，目前提供两种方案。
<ul><li>方案1（推荐）：编写一个类，随便起个名字，继承 JbootAppListenerBase ,然后复写里面的方法。</li><li>方案2（不推荐）：编写自己的JfinalConfig，继承 JbootAppConfig ，然后在 jboot.properties 的 jboot.jfinalConfig 配置上自己的类名。注意，在自己的config中，请优先调用super方法。例如在configConstant中，请先调用super.configConstant(constants)。</li></ul></li></ul></li></ul></div><!----><!----></div></div></div>
    <script src="/assets/js/2.676f353b.js" defer></script><script src="/assets/js/app.7f52c12a.js" defer></script>
  </body>
</html>
